本帖最后由 小篱 于 2015-12-2 15:47 编辑

145815bit4xai8xabubagg.png
  在gif中一帧一帧的看一下,心里大约就有拆分的思路了。

  每个人拆分的可能都不一样,答案本来就不只一种,每个阶段我会写一篇文字,这一篇我们一起看看第一阶段。

  第一阶段是这样的,为了方便大家观看,我放慢了动画速度,

145816147aoq614ssla761.png
  再回头观察动画可知,结束时,O点和D点在0(或2π)处重合,

  因此,结束时可以认为弧是从2π逆时针画到0(虽然0和2π在一个点,但从0到0、从0到2π、从2π到0画弧是不一样的,推荐大家大家动手画一下)

  结束时O、D我们确定了,那么开始的时候呢,我们要看下动画中O、D的运行轨迹了。

  观察动画,我们可以得出O、D的运行轨迹是这样的:

145816fmjmfx5br7jbsmfi.png
  可以看出,O点逆时针(逆时针可以认为角度在减小,可以再参考上文中UIBezierPath的官方文档中的那张图)绕了3/4圈到2π,D点逆时针绕了1.5圈到0;

  因此我们可以得出O、D的角度变化,是这样的:

145817wppxnlxh6673al9x.png
  即O点从7/2的π减小到2π,D点从3π减小到0。

  现在我们知道了O、D的起点,可以将前面图上的文字补全了:

1458171xjfz7xzz0ffwf8z.png
  由此我们可以得出,O、D在动画阶段中的角度(图中的progress取值范围0~1)

145817xtbh4bhc9roc12av.png
  只要我们的progress从0逐渐变到1,我们O、D就逐渐从起点运动到终点了,每次变化的时候绘制从O到D逆时针的弧,我们动画就实现了。

  到了这一步,我们的动画思路已经有了,重要节点的值也知道了,剩下的就是写代码了。

  写代码

  我们的思路可以认为是,属性变化触发重绘

  自定义CALayer的子类,重写它的这两个方法可以实现这个思路

 

 

  1. + (BOOL)needsDisplayForKey:(NSString *)key;
  2. - (void)drawInContext:(CGContextRef)ctx;

 

  1. - (void)drawInContext:(CGContextRef)ctx {
    • UIBezierPath *path = [UIBezierPath bezierPath];
      •  
      • CGFloat radius = MIN(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) / 2 - kLineWidth / 2;
        • CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
          •  
          • // O
            • CGFloat originStart = M_PI * 7 / 2;
              • CGFloat originEnd = M_PI * 2;
                • CGFloat currentOrigin = originStart - (originStart - originEnd) * self.progress;
                  •  
                  • // D
                    • CGFloat destStart = M_PI * 3;
                      • CGFloat destEnd = 0;
                        • CGFloat currentDest = destStart - (destStart - destEnd) * self.progress;
                          •  
                          • [path addArcWithCenter:center radius:radius startAngle: currentOrigin endAngle:currentDest clockwise:NO];
                            • CGContextAddPath(ctx, path.CGPath);
                              • CGContextSetLineWidth(ctx, kLineWidth);
                                • CGContextSetStrokeColorWithColor(ctx, [UIColor blueColor].CGColor);
                                  • CGContextStrokePath(ctx);
                                    • }
复制代码
  至此,第一阶段代码的主要部分就完成了,

  第一阶段的完整代码大家可以参考GitHub上这个项目的OneLoadingAnimationStep1目录。

  上文中的@dynamic progress;的解释

  由于我对property的了解还不深,对此的解释之后会补上,

  目前可参考CALayer.h的这段注释

 

 

  1. /** Property methods. **/
    •  
    • /* CALayer implements the standard NSKeyValueCoding protocol for all
      • * Objective C properties defined by the class and its subclasses. It
        • * dynamically implements missing accessor methods for properties
          • * declared by subclasses.
            • *
复制代码锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛