CAShapeLayer 填充另一个 CAShapeLayer 作为遮罩
CAShapeLayer filling with another CAShapeLayer as a mask
我的问题是关于用另一个 CAShapeLayer
填充动画 CAShapeLayer
。所以,我写了一些代码,几乎实现了我的目标。
我创建了一个基础层并用另一个填充它。代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_shapeLayer = [CAShapeLayer layer];
[self drawBackgroundLayer];
}
// my main/backgound layer
- (void)drawBackgroundLayer {
_shapeLayer.frame = CGRectMake(0, 0, 250, 250);
_shapeLayer.lineWidth = 3;
_shapeLayer.strokeColor = [UIColor blackColor].CGColor;
_shapeLayer.fillColor = UIColor.whiteColor.CGColor;
_shapeLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[self.view.layer addSublayer:_shapeLayer];
[self createCircleLayer];
}
创建一个带圆圈的遮罩层用于填充:
- (void)createCircleLayer {
_shapeLayer.fillColor = UIColor.greenColor.CGColor;
CAShapeLayer *layer = [CAShapeLayer layer];
CGFloat radius = _shapeLayer.bounds.size.width*sqrt(2)/2;
layer.bounds = CGRectMake(0, 0, 2*radius, 2*radius);
layer.position = CGPointMake(_shapeLayer.bounds.size.width/2, _shapeLayer.bounds.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:radius];
layer.path = path.CGPath;
layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
_shapeLayer.mask = layer;
}
//我们的结果是下一个]
所以,让我们为它制作动画。我只是变换图层以填充整个“_shapeLayer”。
- (void)animateMaskLayer:(CAShapeLayer *)maskLayer {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1.0)];
animation.duration = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[newLayer addAnimation:animation forKey:@"transform"];
}
现在,我想对这个绿色层做同样的事情(用红色填充)。
但是当我使用蒙版时,我有明显的红色圆圈和白色背景。
我的目标是有红色圆圈和绿色背景。就像正常填充另一种颜色一样。
使用反掩码也无济于事。
所以,我只是不知道该怎么做。
如果您建议使用:
[_shapeLayer addSublayer:layer];
它不会起作用,因为不仅会有正方形,还会有不同的路径,而且 clipToBounds 不是一个选项。
感谢您的帮助!
所以,解决方法很简单。我只用了两层和一层遮罩层。
第一层:红色层我要用绿色层填充;
- (void)drawBackgroundLayer {
_shapeLayer.frame = CGRectMake(20, 20, 250, 250);
_shapeLayer.lineWidth = 3;
_shapeLayer.strokeColor = [UIColor blackColor].CGColor;
_shapeLayer.lineWidth = 3;
_shapeLayer.fillColor = UIColor.redColor.CGColor;
_shapeLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[self.view.layer addSublayer:_shapeLayer];
[self drawUpperLayer];
}
第二层:我用来填充的绿色层。
- (void)drawUpperLayer {
_upperLayer = [CAShapeLayer layer];
_upperLayer.frame = _shapeLayer.frame;
_upperLayer.lineWidth = 3;
_upperLayer.strokeColor = [UIColor blackColor].CGColor;
_upperLayer.fillColor = UIColor.greenColor.CGColor;
_upperLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[_shapeLayer.superlayer addSublayer:_upperLayer];
}
遮罩层:
- (void)createMaskLayer {
CAShapeLayer *layer = [CAShapeLayer layer];
CGFloat radius = _upperLayer.bounds.size.width*sqrt(2)/2;
layer.bounds = CGRectMake(0, 0, 2*radius, 2*radius);
layer.fillColor = UIColor.blackColor.CGColor;
layer.position = CGPointMake(_upperLayer.bounds.size.width/2, _upperLayer.bounds.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:radius];
layer.path = path.CGPath;
layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
_upperLayer.mask = layer;
}
动画遮罩层:
- (void)animateMaskLayer:(CAShapeLayer *)maskLayer {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1.0)];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[maskLayer addAnimation:animation forKey:@"transform"];
}
因此,生成的动画:
我的问题是关于用另一个 CAShapeLayer
填充动画 CAShapeLayer
。所以,我写了一些代码,几乎实现了我的目标。
我创建了一个基础层并用另一个填充它。代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_shapeLayer = [CAShapeLayer layer];
[self drawBackgroundLayer];
}
// my main/backgound layer
- (void)drawBackgroundLayer {
_shapeLayer.frame = CGRectMake(0, 0, 250, 250);
_shapeLayer.lineWidth = 3;
_shapeLayer.strokeColor = [UIColor blackColor].CGColor;
_shapeLayer.fillColor = UIColor.whiteColor.CGColor;
_shapeLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[self.view.layer addSublayer:_shapeLayer];
[self createCircleLayer];
}
创建一个带圆圈的遮罩层用于填充:
- (void)createCircleLayer {
_shapeLayer.fillColor = UIColor.greenColor.CGColor;
CAShapeLayer *layer = [CAShapeLayer layer];
CGFloat radius = _shapeLayer.bounds.size.width*sqrt(2)/2;
layer.bounds = CGRectMake(0, 0, 2*radius, 2*radius);
layer.position = CGPointMake(_shapeLayer.bounds.size.width/2, _shapeLayer.bounds.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:radius];
layer.path = path.CGPath;
layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
_shapeLayer.mask = layer;
}
//我们的结果是下一个]
所以,让我们为它制作动画。我只是变换图层以填充整个“_shapeLayer”。
- (void)animateMaskLayer:(CAShapeLayer *)maskLayer {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1.0)];
animation.duration = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[newLayer addAnimation:animation forKey:@"transform"];
}
现在,我想对这个绿色层做同样的事情(用红色填充)。 但是当我使用蒙版时,我有明显的红色圆圈和白色背景。 我的目标是有红色圆圈和绿色背景。就像正常填充另一种颜色一样。 使用反掩码也无济于事。 所以,我只是不知道该怎么做。
如果您建议使用:
[_shapeLayer addSublayer:layer];
它不会起作用,因为不仅会有正方形,还会有不同的路径,而且 clipToBounds 不是一个选项。
感谢您的帮助!
所以,解决方法很简单。我只用了两层和一层遮罩层。
第一层:红色层我要用绿色层填充;
- (void)drawBackgroundLayer {
_shapeLayer.frame = CGRectMake(20, 20, 250, 250);
_shapeLayer.lineWidth = 3;
_shapeLayer.strokeColor = [UIColor blackColor].CGColor;
_shapeLayer.lineWidth = 3;
_shapeLayer.fillColor = UIColor.redColor.CGColor;
_shapeLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[self.view.layer addSublayer:_shapeLayer];
[self drawUpperLayer];
}
第二层:我用来填充的绿色层。
- (void)drawUpperLayer {
_upperLayer = [CAShapeLayer layer];
_upperLayer.frame = _shapeLayer.frame;
_upperLayer.lineWidth = 3;
_upperLayer.strokeColor = [UIColor blackColor].CGColor;
_upperLayer.fillColor = UIColor.greenColor.CGColor;
_upperLayer.path = [UIBezierPath bezierPathWithRect:_shapeLayer.bounds].CGPath;
[_shapeLayer.superlayer addSublayer:_upperLayer];
}
遮罩层:
- (void)createMaskLayer {
CAShapeLayer *layer = [CAShapeLayer layer];
CGFloat radius = _upperLayer.bounds.size.width*sqrt(2)/2;
layer.bounds = CGRectMake(0, 0, 2*radius, 2*radius);
layer.fillColor = UIColor.blackColor.CGColor;
layer.position = CGPointMake(_upperLayer.bounds.size.width/2, _upperLayer.bounds.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:radius];
layer.path = path.CGPath;
layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
_upperLayer.mask = layer;
}
动画遮罩层:
- (void)animateMaskLayer:(CAShapeLayer *)maskLayer {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1.0)];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[maskLayer addAnimation:animation forKey:@"transform"];
}
因此,生成的动画: