美文网首页iOS效果原理分析iOS动画iOS Developer
基于CAKeyframeAnimation环绕闪烁效果(过山车效

基于CAKeyframeAnimation环绕闪烁效果(过山车效

作者: 床前明月_光 | 来源:发表于2017-06-02 11:00 被阅读41次

    先看看效果

    环绕效果图

    需求

    这个需求是在为了吸引用户注意到某一个按钮, 或一个View里面的内容提出的. 例如: 滑动解锁按钮, 抽奖按钮等, 恩, 是的, 当你打开一个新的界面的时候, 里面的内容展示比较多的时候, 这样的效果确实能突出重点. 然后我接到需求的时候找了一下相关的知识, 发现没什么思路, 本来知乎上有个人提出的问题跟我的需求很像, 可是没有比较清晰的思路答案, 知乎的问题 iOS 一条线条绕贝塞尔曲线做动画?
    直到我看到了这一篇iOS动画进阶 - CAKeyframeAnimation实现过山车动画然后找到了思路

    实现

    画出两个闪烁点得运动轨迹, 并给两个点设定运动轨迹

    -(void)pathWithClockwise:(BOOL)clockwise {
        CGFloat width = self.frame.size.width;
        CGFloat height = self.frame.size.height;
        CGPoint startPointOne = CGPointMake(height * 0.5, 0);//第一个闪烁开始的点
        CGPoint startPointTwo = CGPointMake(width - height * 0.5, height);//第二个闪烁开始的点
        
        //第一个闪烁的运动轨迹
          UIBezierPath *pathOne = [UIBezierPath bezierPath];
        //第二个闪烁的运动轨迹
        UIBezierPath *pathTwo = [UIBezierPath bezierPath];
        if (clockwise) {//顺时针
          
            [pathOne moveToPoint:startPointOne];
            [pathOne addLineToPoint:CGPointMake(width - height * 0.5, 0)];
            [pathOne addArcWithCenter:CGPointMake(self.frame.size.width - height * 0.5, height * 0.5) radius:height * 0.5 startAngle:-M_PI_2 endAngle:M_PI_2 clockwise:clockwise];
            [pathOne addLineToPoint:CGPointMake(height * 0.5, height)];
            [pathOne addArcWithCenter:CGPointMake(height * 0.5, height * 0.5) radius:height * 0.5 startAngle:M_PI_2 endAngle: -M_PI_2 clockwise:clockwise];
            
           
            [pathTwo moveToPoint:startPointTwo];
            [pathTwo addLineToPoint:CGPointMake(height * 0.5, height)];
            [pathTwo addArcWithCenter:CGPointMake(height * 0.5, height * 0.5) radius:height * 0.5 startAngle:M_PI_2 endAngle: -M_PI_2 clockwise:clockwise];
            [pathTwo addLineToPoint:CGPointMake(width - height * 0.5, 0)];
            [pathTwo addArcWithCenter:CGPointMake(self.frame.size.width - height * 0.5, height * 0.5) radius:height * 0.5 startAngle:-M_PI_2 endAngle:M_PI_2 clockwise:clockwise];
        }else {//逆时针
            [pathOne moveToPoint:startPointOne];
            [pathOne addArcWithCenter:CGPointMake(height * 0.5, height * 0.5) radius:height * 0.5 startAngle:-M_PI_2 endAngle:M_PI_2 clockwise:clockwise];
            [pathOne addLineToPoint:startPointTwo];
            [pathOne addArcWithCenter:CGPointMake(self.frame.size.width - height * 0.5, height * 0.5) radius:height * 0.5 startAngle:M_PI_2 endAngle: -M_PI_2 clockwise:clockwise];
            [pathOne addLineToPoint:startPointOne];
            
            
            [pathTwo moveToPoint:startPointTwo];
            [pathTwo addArcWithCenter:CGPointMake(self.frame.size.width - height * 0.5, height * 0.5) radius:height * 0.5 startAngle:M_PI_2 endAngle: -M_PI_2 clockwise:clockwise];
            [pathTwo addLineToPoint:startPointOne];
            [pathTwo addArcWithCenter:CGPointMake(height * 0.5, height * 0.5) radius:height * 0.5 startAngle:-M_PI_2 endAngle:M_PI_2 clockwise:clockwise];
            [pathTwo addLineToPoint:startPointTwo];
        
        }
       
        
        
        //显示的轨迹
        CAShapeLayer *pathLayer = [CAShapeLayer layer];
        pathLayer.path = pathOne.CGPath;
        pathLayer.lineCap = kCALineCapRound;
        pathLayer.strokeColor = [UIColor orangeColor].CGColor;
        pathLayer.lineWidth = 2;
        pathLayer.fillColor = [UIColor clearColor].CGColor;
        [self.layer addSublayer:pathLayer];
    
        //开始两个闪烁动画
        [self startAnimationWith:pathOne startPostion:startPointOne];
        [self startAnimationWith:pathTwo startPostion:startPointTwo];
    
    }
    

    创建闪烁的点, 根据透明度拼成一条渐变的线段

    -(void)startAnimationWith:(UIBezierPath *)path startPostion:(CGPoint)point {
        for (int i = 0; i < 20; i++) {
            //创建粒子
            CALayer *dotLayer = [CALayer layer];
            dotLayer.frame = CGRectMake(point.x, point.y, 4, 4);
            dotLayer.backgroundColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:(1-0.05*i)].CGColor;
            [self.layer addSublayer:dotLayer];
            CAKeyframeAnimation *anim = [self animationWithPath:path withIndex:i];
            [dotLayer addAnimation:anim forKey:nil];
        }
    
    }
    

    然后给线段的每个点执行动画

    -(CAKeyframeAnimation *)animationWithPath:(UIBezierPath *)path  withIndex:(int)index{
        //添加帧动画
        CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
        anim.keyPath = @"position";
        anim.path = path.CGPath;
        anim.repeatCount = MAXFLOAT;
        anim.calculationMode = kCAAnimationPaced;
        //动画速度为匀速
        anim.calculationMode = kCAAnimationCubicPaced;
        //动画角度是否调整
        anim.rotationMode = kCAAnimationRotateAuto;
        anim.fillMode = kCAFillModeForwards;
        anim.removedOnCompletion = NO;
        anim.duration = 1.5;
        anim.beginTime = CACurrentMediaTime() + 0.01 * index;
        anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        return anim;
    }
    

    另外一种思路

    本来是想用CAShapeLayer作为运动的线段的, 而不是一个个点拼成的线段. CAShapeLayer上做 " strokeStart" 和 "strokeEnd"结合的. 但是细节看起来很丑, 可能是我处理的不够, 如果你有更好的思路欢迎告诉我.

    最后附上 DEMO

    相关文章

      网友评论

        本文标题:基于CAKeyframeAnimation环绕闪烁效果(过山车效

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