codecamp

iOS 动画解析 支付宝支付动画 上

平时在用支付宝付款时,会有一个支付中的动画和一个支付完成的动画。这篇博客主要分析一下 支付中 的动画效果,效果如下:

支付宝支付动画

一、动画解析

为了方便观察,添加了放慢加载动画的速度并添加辅助线:

放慢后的动画

从图中可以看出:加载圆弧运动轨迹可分为前半段后半段;并且圆弧的起始角度(StartAngle)和结束角度(EndAngle)在做有规律的变化;

前半段: 从-0.5π到π,这一段运动中速度较快;StartAngle不变,始终未-0.5π;EndAngle在匀速上升,一直到π;前半段中圆弧不断变长,最后形成一个3/4的圆。

后半段: 从π到1.5π,这一段运动速度较慢;StartAngle开始变化,从-0.5π变化到1.5π;EndAngle从π变化到1.5π,最后StartAngle和EndAngle重合于1.5π;后半段中圆弧不断变长,最后直至消失。

二、实现代码

1、初始化一些全局属性

{
    //刷新工具
    CADisplayLink *_link;
    //显示圆环
    CAShapeLayer *_animationLayer;
    //起始角度
    CGFloat _startAngle;
    //结束角度
    CGFloat _endAngle;
    //当前动画进度
    CGFloat _progress;
}

2、界面刷新工作由CADisplayLink来完成

    _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction)];
    [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    _link.paused = true;

为了实现前半段后半段的速度区别,定义了一个速度方法:

-(CGFloat)speed{
    if (_endAngle > M_PI) {
        return 0.1/60.0f;
    }
    return 0.8/60.0f;
}

通过CADisplayLink刷新进度,进度增长的快慢有speed决定:

-(void)displayLinkAction{
    _progress += [self speed];
    if (_progress >= 1) {
        _progress = 0;
    }
    [self updateAnimationLayer];
}

刷新贝塞尔曲线的StartAngle和EndAngle实现曲线的运动:

-(void)updateAnimationLayer{

    
    _startAngle = -M_PI_2;
    _endAngle = -M_PI_2 +_progress * M_PI * 2;

    
    if (_endAngle > M_PI) {
        CGFloat progress1 = 1 - (1 - _progress)/0.25;
        _startAngle = -M_PI_2 + progress1 * M_PI * 2;
    }
    CGFloat radius = _animationLayer.bounds.size.width/2.0f - lineWidth/2.0f;
    CGFloat centerX = _animationLayer.bounds.size.width/2.0f;
    CGFloat centerY = _animationLayer.bounds.size.height/2.0f;
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(centerX, centerY) radius:radius startAngle:_startAngle endAngle:_endAngle clockwise:true];
    path.lineCapStyle = kCGLineCapRound;

    
    _animationLayer.path = path.CGPath;
}

Github

iOS 动画解析 支付宝支付动画 下
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }