Nice标签动画分析

作者: 柏江舟 | 来源:发表于2015-04-05 18:58 被阅读636次

    layout: post
    title: "Nice 标签动画分析"
    date: 2015-04-05 16:51:25 +0800
    comments: true
    categories: iOS 动画


    Demo动画Demo动画

    上图是模仿nice中的标签,接下来分析构建这个控件的过程。

    开始需要看下iOS的显示动画 以及 CAAnimationGroup

    1. 中间icon的放大缩小动画

    首先给layer设置image icon,

    layer.contents = (__bridge id)(icon.CGImage);
    

    通过 “transform.scale”这个keypath 来收缩layer,缩放过程如下:
    1 缩小到0.8倍
    2 放大到1.2倍
    3 复原到1.0倍

        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        animation.fromValue = @1;
        animation.toValue = @0.8;
        animation.duration = 0.2;
    
        CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        animation1.fromValue = @0.8;
        animation1.toValue = @1.2;
        animation1.duration = 0.4;
        animation1.beginTime = animation.duration;
        
        CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        animation2.fromValue = @1.2;
        animation2.toValue = @1;
        animation2.duration = 0.2;
        animation2.beginTime = animation.duration + animation1.duration;
    
        CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
        animationGroup.duration = animation.duration + animation1.duration + animation2.duration + 0.1;
        animationGroup.repeatCount = 0;
        animationGroup.delegate = self;
        animationGroup.animations = @[animation,animation1,animation2];
        [animationGroup setValue:@"icon" forKey:@"animationName"];
            ``` 
    CAAnimationGroup中的动画都是并发执行的,所以icon动画关键是通过beginTime设置每个动画开始播放的时间,repeatCount=0,所有动画都为单次播放。
    ## 2. 脉冲动画
    ```objc
        CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        animation3.fromValue = @0.0;
        animation3.toValue = @1.0;
        animation3.duration = duration;
        //关键帧动画
        CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
        animation4.duration =duration ;
        animation4.values = @[@0.8, @0.45, @0];
        animation4.keyTimes = @[@0, @0.2, @1];
        
            CAAnimationGroup *animationGroup = [CAAnimationGroup animation];        
        .......
         [animationGroup setValue:@"pulse" forKey:@"animationName"];
    
        ```
    通过CAAnimationGroup来实现layer一边放大,一边设置透明度来实现脉冲效果,
    ## 3. 通过Animation的delegate来组合动画
    看图是整个动画是由 一个收缩动画 两个脉冲动画组合起来的,组合过程就是由各个CAAnimationGroup的delegate来合成的
     
     ```objc
       - (void)animationDidStart:(CAAnimation *)animation{        //等第一个脉冲动画播放到0.5秒,开始播放第二个动画
            NSString *animationName = [animation valueForKey:@"animationName"];
            if ([animationName  isEqualToString:@"pulse"]) {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * self.pulsingGroup.duration  * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [pulsingLayer1 addAnimation:pulsingGroup1 forKey:@"pulse1"];
                });
            }
      }
        - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished{
            NSString *animationName = [animation valueForKey:@"animationName"];
            if ([animationName isEqualToString:@"icon"]) { //icon动画播放完结束后添加脉冲动画
                [imageLayer removeAnimationForKey:@"icon"];
                [pulsingLayer addAnimation:pulsingGroup forKey:@"pulse"];
            }else if ([animationName isEqualToString:@"pulse"]){ //第一个脉冲动画播放完成后移除
                [pulsingLayer removeAnimationForKey:@"pulse"];
            }else if ([animationName isEqualToString:@"pulse1"]){//第二个脉冲动画播放后,再开始循环播放icon动画
                [pulsingLayer1 removeAnimationForKey:@"pulse1"];
                [imageLayer addAnimation:iconGroup forKey:@"icon"];
            }
    }
    

    4. 绘制箭头

    首先计算tag上文字的宽度加上 除去文字的其他宽度,算出tag的宽度, 然后找到这个箭头的5个角, 通过addArcWithCenter 这个方法 (在每个角上画上一个圆,确定每个圆的半径、圆心以及角度。) 分别在5个角上画5段弧线。然后 使用 [path fill]来填充背景颜色。

    5. 绘制文字

    NSDictionary *attributes = @{
                                       NSShadowAttributeName : shadow,
                                       NSForegroundColorAttributeName : [UIColor colorWithRed:255 green:255 blue:255 alpha:1],
                                       NSFontAttributeName : [UIFont systemFontOfSize:14]
                                       };
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes];
    [attributedText  drawInRect:CGRectMake(0,0,100,height)]
    

    总结

    整个控件的动画都是由CAAnimationGroup的delegate调度的,每个CAAnimationGroup完成后,继续另外一个动画。 绘制箭头的时候比较麻烦的是确定每个圆角的角度、半径与圆点,最好在Photoshop或者Sketch上确定好。
    在使用过程中,有可能需要需要缩小,这个时候可以通过view的矩阵变换 transform CGAffineTransformMakeScale 来设置大小。

    点击下载Demo

    相关文章

      网友评论

      本文标题:Nice标签动画分析

      本文链接:https://www.haomeiwen.com/subject/ltaaxttx.html