本教程为系列教程第二篇。第一篇教程传送门

第一篇系列教程我们实现如图效果:
第一篇
本系列教程,我们要实现如下效果。
第二篇
看到如上效果我们是否会想到第一篇中所了解的重绘弧。但是本篇中此弧度固定,并未有任何变化,我们可以使用苹果为我们提供的一个简单对象CAShapeLayer.此CAShapeLayer 有两种属性StrokeStartStrokeEnd . ps : 值范围为 0.0~1.0

StrokeStart :  shapeLayer显示路径颜色的开始位置
StrokeEnd : shapeLayer 显示路径颜色的终点位置

开始

由上图我们看到红色部分沿弧长运行。假设红色部分是弧长的0.1,那么弧长的起始StrokeStart 从 0.0 变为 0.9 ,StrokeEnd 从 0.1 变为1.0 , 使其红色部分永久相差0.1。

根据第一篇形成的圆以及动画的效果图,我们可知如下图:
计算图
黄色弧度线即为所求的弧长。
假设红色部分运动到小圆球顶点的半径高度。由此可得图中公式。

d = r / 2;

我们可得大圆的各个数据:

  //小圆心
    CGPoint center = CGPointMake(CGRectGetMidX(self.view.layer.bounds), CGRectGetMidY(self.view.layer.bounds));
 //小圆半径 (减去的为线宽)
    CGFloat kRadius = CGRectGetWidth(_layer.bounds) * 0.5 - 5 * 2 ;
 //d 的长度
    CGFloat d = kRadius / 2;
 //大圆的圆心
    CGPoint arcCenter = CGPointMake(center.x - d - kRadius, center.y);
//大圆的半径
     CGFloat arcRadius = 2 * kRadius + d;
//红色部分所划过的角度
     CGFloat endAngle =  - asin(2*kRadius / arcRadius);

因此我们可以创建CAShapeLayer的路径。

 CAShapeLayer * moveLayer = [CAShapeLayer layer];
  moveLayer.bounds = self.view.bounds;  //ViewController 的View大小
  moveLayer.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
     //圆心
 UIBezierPath * path  = [UIBezierPath bezierPath] ;
 [path addArcWithCenter:arcCenter radius:arcRadius startAngle:0 endAngle:endAngle clockwise:NO];
 moveLayer.path = path.CGPath;
 moveLayer.strokeColor = [UIColor redColor].CGColor;
 moveLayer.lineWidth = 3;
 moveLayer.fillColor = nil; //如果不设置此项,会有默认黑色背景
[self.view.layer addSublayer:moveLayer];

此时我们通过CABasicAnimation设置strokeStartstrokeEnd 组合动画。

CABasicAnimation * startAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
startAnimation.fromValue = @(0.0);
startAnimation.toValue = @(0.9);

 CABasicAnimation * endAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
endAnimation.fromValue = @(0.1);
endAnimation.toValue = @(1.0);

 CAAnimationGroup * group = [CAAnimationGroup animation];
group.animations = @[startAnimation,endAnimation];
group.duration = 3;
group.repeatCount = MAXFLOAT;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[_moveLayer addAnimation:group forKey:nil];

至此,效果已经实现。

##完整代码请下载