• iOS动画原理


    1. iOS动画原理

    • 本质:动画对象(这里是UIView)的状态,基于时间变化的反应
    • 分类:可以分为显式动画(关键帧动画和逐帧动画)和隐式动画
    • 关键帧和逐帧总结:关键帧动画的实现方式,只需要修改某个属性值就可以了,简单方便,但涉及的深层次内容较多,需要更多的理解和练习。采用逐帧动画的实现方式,实现原理简单,但绘制动画的过程要复杂。如果动画过程处理的事情较多,也会带来较大的开销,就有可能造成动画帧数的下降,出现卡顿的现象,因此需要较多的测试和调试。

    1.1 显式动画(逐帧动画和关键帧动画)

    显式动画本质是我们显式地给CALayer添加一个动画

    • 逐帧动画

      • 用户需要周期性的调用绘制方法,绘制每帧的动画对象,系统操作方法简单,但用户操作的工作量就会大一些
      • 周期性这边指的是定时器CADisplayLink,其基于屏幕刷效率的,即屏幕每次刷新时就会触发调用(iPhone为60FPS)。
      • 绘制指的是对UIView背后对应的主CALayer进行的修改,这边的修改包括- drawRect:方法和UIView的属性渐变(改变颜色尺寸等)。
      • 注意1:因为有些时候绘制过程相对复杂,所以一般采用每隔一帧进行绘制,相当于30FPS的刷新率。另外著名的pop动画框架,就是用CADisplayLink进行的逐帧动画。
      • 注意2:如果在逐帧绘制的方法中修改了一个自建的CALayer,这个CALayer不是对应某个UIView的,需注意系统的隐式动画的影响,后面会提到这点。
    • 关键帧动画

      • 主要是使用两个关键帧---起始帧和结束帧,再配合别的关键信息(如动画时间和运动类型等)
      • 每个CALayer都有一个属性来表示成坐标,我们可以修改模型层modelLayer来改变展现层presentationLayer来形成动画效果。
      • 整个动画过程,通过坐标层次来看如下所示:
        • 动画前,显示模型层的当前值;
        • 动画开始,切换显示展现层的值;
        • 动画过程中,展现层的值根据时间变化,我们看到的实际是展现层的值在变化;
        • 动画结束,切换回显示模型层的值,此时模型层的值应被修改为动画结束时的值。
      • 代码注释如下:
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        view.backgroundColor = [UIColor redColor];
        [self.view addSubview:view];
        
        // CABasicAnimation指定一个keyPath,详见官方API
        // 常见keyPath:transform.scale/transform.translation.x/position.x(非3D平移)
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
        // 开始帧
        animationWithKeyPath.fromValue = @(100);
        // 结束帧
        animationWithKeyPath.fromValue = @(200);
        // 动画时间
        animation.duration = 2.0;
        // 永久重复动画
        animation.repeatCount = HUGE;
        // 代理方法:
        // - (void)animationDidStart:(CAAnimation *)anim;
        // - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
        animation.delegate = self;
        // fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
        animation.fillMode = kCAFillModeForwards;
        // removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
        animation.removedOnCompletion = NO;
        // autoreverses:动画结束时是否执行逆动画
        animation.autoreverses = NO;
        // timingFunction:动画类型,设定动画的速度变化
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        // 给CALayer添加一个动画,该动画为CAAnimation类型,其子类有CABasicAnimation/CAKeyframeAnimation/CAAnimationGroup/CATransition(图层过度动画,有filter属性)
        [view.layer addAnimation:animation forKey:nil];
        

    1.2 隐式动画

    当前UIView的主CALayer称为根层,自动另外创建的CALayer为非根层,对非根层的部分可动画属性修改时,就是隐式动画。

    • 直接对UIView或其CALayer设置一个可动画的属性值时,会出发系统的隐式动画,可动画的属性值,可以在UIView或其CALayer的文档中找到,属性标有Animatable
    • 注意:
      • 因为主CALayer,系统默认关闭了隐式动画,所以当我们直接修改这些可动画属性值时,变化时直接生效的,没有动画效果。
      • 如果修改的是一个自建的单独CALayer时,帧与帧之间的变化还是会触发系统的默认隐式动画,这个时候就需要我们来手动关闭隐式动画
      • 隐式动画所做的事情和显示动画是一样的,我们设置的属性值都是模型层的数值,而系统会自动添加属性对应的CAAnimation动画到CALayer上。
      • UIView有一系列的animateWithDuration动画方法,在这些方法中UIView会恢复隐式动画,所以在动画的block中修改属性时,又会触发隐式动画。
  • 相关阅读:
    html 输入框 只能输入数字 只能输入字母数字 等组合
    element中table高度自适应问题
    设置千分位问题(改变数据结构形式--转成字符串)
    在element的table接受数据设置千分位问题(不改变数据类型)
    element在使用tab页时,echarts只在第一个页面加载(第二个tab页也在默认tab页显示)问题
    css1
    B/S(Web)实时通讯解决方案
    WebRTC介绍及简单应用
    webpack的编译流程
    01 写一个 mySetInterVal(fn, a, b),每次间隔 a,a+b,a+2b 的时间,然后写一个 myClear,停止上面的 mySetInterVal
  • 原文地址:https://www.cnblogs.com/LongLJ/p/6113347.html
Copyright © 2020-2023  润新知