CAShapeLayer filling with another CAShapeLayer as a mask

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

My question is about filling animation one CAShapeLayer with another CAShapeLayer. So, I wrote some code that almost achieves my goal.

I created a based layer and fill it with another. Code below:

- (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];  } 

Create a circled mask layer for filling:

- (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;  } 

// our result is next]

So, let's animate it. I just transform the layer to fill the whole "_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"]; } 

Now, I want to do the same with this green layer (fill it with red color). But when I use the mask I have red circle and the white background what is obviously. My goal here is to have red circle and green background. Like normal filling with another color. By using inverse mask won't help neither. So, I just have no ideas how to do it.

If you suggest using:

[_shapeLayer addSublayer:layer]; 

it won't work as there will be not only square but different paths and clipToBounds is not an option.

Thank you for any help!

回答1:

So, the solution is simple. I just use two layers and one mask layer.

First layer: Red layer I want to fill with green layer;

- (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]; } 

Second Layer: Green Layer I use for filling.

- (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];  } 

Mask Layer:

- (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; } 

Animate 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"]; } 

So, resulted animation:



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!