I'm changing CAShapeLayer's path in for
loop, but it only shows the last result of loop. I know, that I can do that with CABasicAnimation but I need to change path this way. Any ideas how to do that?
UIBezierPath *path = [ShapeManager getCirclePathAppendedWithCirclePathWithRadius:radius
andFrame:self.view.bounds];
self.layer.fillRule = kCAFillRuleEvenOdd;
self.layer.fillColor = [UIColor grayColor].CGColor;
self.layer.opacity = 0.5;
self.layer.path = path.CGPath;
[self.view.layer addSublayer:self.layer];
for (int i = 1; i < 100; ++i) {
path = [ShapeManager getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width-i
andFrame:self.view.bounds];
self.layer.path = path.CGPath;
}
helper methods
+ (UIBezierPath *)getCirclePathAppendedWithCirclePathWithRadius:(CGFloat)radius andFrame:(CGRect)frame {
UIBezierPath *backgroundPath = [UIBezierPath bezierPathWithRect:frame];
[backgroundPath appendPath:[self getCirclePathWithRadius:radius andFrame:frame]];
return backgroundPath;
}
+ (UIBezierPath *)getCirclePathWithRadius:(CGFloat)radius andFrame:(CGRect)frame {
CGRect rect = frame;
UIBezierPath *circlePath;
circlePath = [UIBezierPath bezierPathWithArcCenter:(CGPoint){rect.size.width/2, rect.size.height/2} radius:radius startAngle:0 endAngle:M_PI*2 clockwise:YES];
return circlePath;
}
You're right about using CABasicAnimation.
for
loop, it is not going to do the job. CABasicAnimation
for path
key with values to interpolate between. This code should be called only once in viewDidLoad
method:UIBezierPath *fromPath = [self.class getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width andFrame:self.view.bounds];
UIBezierPath *toPath = [self.class getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width-99 andFrame:self.view.bounds];
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.fromValue = (id)fromPath.CGPath;
animation.toValue = (id)toPath.CGPath;
animation.duration = 1;
[layer addAnimation:animation forKey:@"pathAnimation"];
layer.speed = 0;
Update:
speed
value to 0 because you're going to set animation progress manually:@property (nonatomic, assign) double progress;
- (void) setProgress: (double) progress {
_progress = progress;
layer.timeOffset = (CFTimeInterval)progress;
}
This assumes that animation duration is 1.0. Otherwise you need to set
layer.timeOffset = (CFTimeInterval)(progress * totalDuration);
Now just set progress in motion callback according to the updated value.