iOS 拆分一个跟随动画

效果图:2018-05-16 17_05_51.gif

主要还是对layerstrokeStartstrokeEnd 做动画。

首先是两个sublayer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
-(void)initilize{
//线宽可以自己设置
CGFloat lineWidth = 10;
CGPoint point = CGPointMake(self.width/2, self.height/2);
UIBezierPath *path =[UIBezierPath bezierPathWithArcCenter:point radius:(self.width - lineWidth)/2 startAngle:0 endAngle:2 *M_PI clockwise:YES];
self.layer1 =[[CAShapeLayer alloc]init];
self.layer1.frame = self. bounds;
self.layer1.strokeColor = [UIColor hexStringToColor:@"#55a34a"].CGColor;
self.layer1.fillColor =[UIColor clearColor].CGColor;
self.layer1.lineWidth = lineWidth;
self.layer1.strokeEnd = 0;
self.layer1.lineCap = kCALineCapRound;
self.layer1.path = path.CGPath;
[self.layer addSublayer:self.layer1];
UIBezierPath *path2 =[UIBezierPath bezierPathWithArcCenter:point radius:(self.width - lineWidth)/2 startAngle:M_PI endAngle:3 *M_PI clockwise:YES];
self.layer2 =[[CAShapeLayer alloc]init];
self.layer2.frame = self. bounds;
self.layer2.strokeColor = [UIColor hexStringToColor:@"#55a34a"].CGColor;
self.layer2.fillColor =[UIColor clearColor].CGColor;
self.layer2.lineWidth = lineWidth;
self.layer2.strokeEnd = 0.00 ;
self.layer2.lineCap = kCALineCapRound;
self.layer2.path = path2.CGPath;
[self.layer addSublayer:self.layer2];
[self animationFirst];
}

每个layer添加都动画都是一样的,只是path的startAngle,endAngle不同罢了。

添加动画:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
-(void)addAnimation:(CAShapeLayer *)parentLayer animationValue:(NSString *)animationValue{
CAAnimationGroup *group = [CAAnimationGroup animation];
parentLayer.strokeStart=0;
//设置strokeEnd的最终值,动画的fromValue为0,
parentLayer.strokeEnd= 0;
CAKeyframeAnimation *animation1 =[CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
animation1.values = @[@0.00,@0.05,@0.7,@0.8,@1,@0.05];
animation1.keyTimes = @[@0.00,@0.05,@0.7,@0.8,@0.9,@1];
CAKeyframeAnimation *animation2 =[CAKeyframeAnimation animationWithKeyPath:@"strokeStart"];
animation2.values = @[@0.00,@0.3,@0.4,@1,@0.05];
animation2.keyTimes = @[@0.00,@0.7,@0.8,@0.9,@1];
group.animations = @[animation1,animation2];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
group.repeatCount = INT_MAX;
group.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
group.duration = 5;
group.delegate = self;
[group setValue:animationValue forKey:@"animationName"];
[parentLayer addAnimation:group forKey:@"animationName"];
}

执行动画:

1
2
3
4
5
6
-(void)animationFirst{
[self addAnimation:self.layer1 animationValue:@"layoneAnimation"];
[self addAnimation:self.layer2 animationValue:@"layTwoAnimation"];
}

如果设置动画重复,动画会不连贯,所以在动画结束的时候重新开始动画:

1
2
3
4
5
6
7
8
9
10
11
12
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if ([[anim valueForKey:@"animationName"] isEqualToString:@"layoneAnimation"]) {
[self addAnimation:self.layer1 animationValue:@"layoneAnimation"];
}
if ([[anim valueForKey:@"animationName"] isEqualToString:@"layTwoAnimation"]) {
[self addAnimation:self.layer2 animationValue:@"layTwoAnimation"];
}
}

demo 收录在 ProgressViewDemo 中。