关于ios:iOS-动画全面总结

10次阅读

共计 11951 个字符,预计需要花费 30 分钟才能阅读完成。

动画 – UIKit

动画原理

  • 视觉残留效应
  • 静止含糊

做动画的时候要达到 60FPS 时候,画面能力晦涩,不然用户会感觉界面卡顿。

UIView 提供的动画反对

UIView 动画实质上对 Core Animation 的封装,提供一个简洁好用的动画接口,在要求不简单的状况下,齐全能够实现很多动画。
UIView 动画能够设置的动画属性有:

  • frame / bounds 大小变动
  • center 核心地位
  • transform 旋转平移等
  • alpha 透明度
  • backgroundColor 背景色彩
  • contentStretch 拉伸内容
  • Autolayout 环境下的动画要间接批改 constraint, 留神 setNeedsUpdateConstraints,layoutIfNeeded 的用法

UIView 类办法动画

  • 动画的开始和完结办法
  • UIView Block 动画
  • Spring 动画
  • Keyframes 动画
  • 转场动画

    • 单个视图的过渡
    • 从旧视图到新视图的过渡
1. 动画的开始和完结办法

根本语句:

动画开始完结标记
UIView.beginAnimations(String?, context: UnsafeMutablePointer<Void>)
第一个参数是动画标识,第二个参数是附加参数,在设置了代理的状况下,此参数将发送setAnimationWillStartSelector setAnimationDidStopSelector 所指定的办法,个别设为 nil。

UIView.commitAnimations() 动画完结

动画参数设置办法

  • UIView.setAnimationDelay(NSTimeInterval) 设置动画的延时
  • UIView.setAnimationDuration(NSTimeInterval) 设置动画持续时间
  • UIView.setAnimationDelegate(AnyObject?) 设置动画代理
  • UIView.setAnimationWillStartSelector(Selector) 设置动画行将开始时代理执行的 SEL
  • UIView.setAnimationDidStopSelector(Selector) 设置动画完结时代理对象执行的 SEL
  • UIView.setAnimationRepeatCount(Float) 设置动画的反复次数
  • UIView.setAnimationCurve(UIViewAnimationCurve) 设置动画的曲线
  • UIView.setAnimationRepeatAutoreverses(Bool) 设置动画是否继续执行相同的动画
  • UIView.setAnimationsEnabled(Bool) 是否禁用动画成果(对象属性仍然会被扭转,只是没有动画成果)
  • UIView.setAnimationBeginsFromCurrentState(Bool) 设置是否从以后状态开始播放动画

    • 假如上一个动画正在播放,且尚未播放结束,咱们将要进行一个新的动画:
    • 当为 true 时:动画将从上一个动画所在的状态开始播放
    • 当为 false 时:动画将从上一个动画所指定的最终状态开始播放(此时上一个动画马上完结)

以下是简略的例子:

2. UIView Block 动画

1)最简略的 Block 动画 蕴含工夫和动画

UIView.animateWithDuration(NSTimeInterval) { // 动画持续时间 
            <#code#>// 执行动画
        }

2)带有动画实现回调的 Block 动画

UIView.animateWithDuration(NSTimeInterval, animations: {<#code#>// 执行动画}) {(Bool) in
                <#code#>// 动画结束后执行的操作
        }

3)能够设置提早和过渡成果 Block 动画

 UIView.animateWithDuration(NSTimeInterval, delay: NSTimeInterval, options: UIViewAnimationOptions, animations: {<#code#>}) {(<#Bool#>) in
                <#code#>
        }

留神,此处的 UIViewAnimationOptions 能够组合应用, 在 swift 中写法 options: [UIViewAnimationOptions.CurveEaseInOut, UIViewAnimationOptions.Repeat]
具体的枚举值,看官网文档即可。

4)Spring 动画
iOS7 后新增 Spring 动画,iOS 零碎动画大部分采纳 Spring Animation。

UIView.animateWithDuration(NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: {<#code#>}) {(<#Bool#>) in
                <#code#>
        }
  • Duration: 动画持续时间
  • delay: 动画执行延时
  • usingSpringWithDamping: 触动成果,范畴 0~1,数值越小,触动成果越显著
  • initialSpringVelocity: 初始速度
  • options: 动画的过渡成果

5)Keyframes 关键帧动画

UIView.animateKeyframesWithDuration(NSTimeInterval, delay: NSTimeInterval, options: UIViewKeyframeAnimationOptions, animations: {<#code#>}) {(<#Bool#>) in
                <#code#>
        }

减少关键帧的办法

UIView.addKeyframeWithRelativeStartTime(Double, relativeDuration: Double, animations: {<#code#>})

留神开始工夫和持续时间均是占总工夫的比例

UIViewKeyframeAnimationOptions 的枚举值如下,能够组合应用

UIViewAnimationOptionLayoutSubviews           // 进行动画时布局子控件
UIViewAnimationOptionAllowUserInteraction     // 进行动画时容许用户交互
UIViewAnimationOptionBeginFromCurrentState    // 从以后状态开始动画
UIViewAnimationOptionRepeat                   // 有限反复执行动画
UIViewAnimationOptionAutoreverse              // 执行动画回路
UIViewAnimationOptionOverrideInheritedDuration // 疏忽嵌套动画的执行工夫设置
UIViewAnimationOptionOverrideInheritedOptions // 不继承父动画设置

UIViewKeyframeAnimationOptionCalculationModeLinear     // 运算模式 : 间断
UIViewKeyframeAnimationOptionCalculationModeDiscrete   // 运算模式 : 离散
UIViewKeyframeAnimationOptionCalculationModePaced      // 运算模式 : 平均执行
UIViewKeyframeAnimationOptionCalculationModeCubic      // 运算模式 : 平滑
UIViewKeyframeAnimationOptionCalculationModeCubicPaced // 运算模式 : 平滑平均

关键帧动画:

private func blockAni5() {
        UIView.animateKeyframesWithDuration(5, delay: 0.0, options: UIViewKeyframeAnimationOptions.CalculationModeLinear, animations: {
            UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 1.0/4, animations: {self.greenView.backgroundColor = UIColor.redColor()
            })
            
            UIView.addKeyframeWithRelativeStartTime(1.0/4, relativeDuration: 1.0/4, animations: {self.greenView.backgroundColor = UIColor.blackColor()
                self.greenView.frame.size = CGSize(width: 50, height: 50)
            })
            
            UIView.addKeyframeWithRelativeStartTime(2.0/4, relativeDuration: 1.0/4, animations: {self.greenView.backgroundColor = UIColor.yellowColor()
            })
            UIView.addKeyframeWithRelativeStartTime(3.0/4, relativeDuration: 1.0/4, animations: {self.greenView.backgroundColor = UIColor.blueColor()
                self.greenView.frame.size = CGSize(width: 250, height: 250)
            })
            
            
            
            }) {(_) in
                print("动画实现 blockAni5()")
        }
    }

简略的例子:

3. UIView 转场动画

在进行示例之前,大家须要留神一点过渡转变动画与动画属性动画的不同之处。咱们在创立动画属性动画时只须要在 animations 闭包中增加对视图动画属性批改的代码即可,它没有作用域或作用视图的概念。而在过渡转变动画中有作用视图的概念,也就是说咱们调用过渡转变动画办法时须要指定一个作用视图

过渡转变动画中的作用视图并不是咱们的指标视图,而是指标视图的容器视图,那么大家不难想象,如果该容器视图中有多个子视图,那么这些子视图都会有过渡转变动画成果。

1)从旧视图到新视图的转场

 UIView.transitionFromView(UIView, toView: UIView, duration: NSTimeInterval, options: UIViewAnimationOptions) {(<#Bool#>) in
            <#code#>
        }

在该动画过程中,fromView 会从父视图中移除,并将 toView 增加到父视图中。转场动画的作用对象是父视图,过渡成果体现在父视图上

2)单个试图的过渡

UIView.transitionWithView(UIView, duration: NSTimeInterval, options: UIViewAnimationOptions, animations: {<#code#>}) {(<#Bool#>) in
                <#code#>
        }

简略的例子

外围动画 CoreAnimations

Core Animation(外围动画)是一组弱小的动画 API,是间接操作 CALayer 层来产生动画,相比上述的 UIView 动画,能够实现更简单的动画成果。

事务管理 CATransaction

CALayer 的可用于动画的属性成为 Animatable properties,苹果官网有具体的列表,显示了所有了能够动画的属性 CALayer Animatable Properties。如果一个 Layer 对象对应着 View,则称这个 Layer 是一个 Root Layer, 非 Root Layer 个别是通过 CALayer 或者其子类间接创立的。
所有的非 Root Layer 在设置 Amimation Properties 的时候都存在隐式动画,默认的 duration 是 0.25 秒

事务(transaction)实际上是 Core Animation 用来蕴含一系列属性动画汇合的机制,用指定事务去扭转能够做动画的图层属性,不会立即发生变化,而是提交事务时用一个动画过渡到新值。任何 Layer 的可动画属性的设置都属于某个 CATransaction,事务的作用是为了保障多个属性的变动同时进行。事务能够嵌套,当事务嵌套时候,只有最外层的事务 commit 之后,整个动画才开始。

CATransaction 没有任何实例办法,只有类型办法。CATransaction.begin()CATransaction.commit() 形成了一个动画块:

CATransaction.begin()
/* animation block */
CATransaction.commit()

其余的办法

func animationDuration() -> CFTimeInterval  // get duration, defaults to 0.25s
func setAnimationDuration(dur: CFTimeInterval)  // set duration
func animationTimingFunction() -> CAMediaTimingFunction?  // get timing function
func setAnimationTimingFunction(function: CAMediaTimingFunction?)  // set timing function
func disableActions() -> Bool  // get disable actions state
func setDisableActions(flag: Bool)  // set disable actions state
func completionBlock() -> (() -> Void)?  // get completion block
func setCompletionBlock(block: (() -> Void)?)  // set completion block

以上四组的办法能够用以下两个办法代替

func valueForKey(key: String) -> AnyObject?
func setValue(anObject: AnyObject?, forKey key: String)

CATransaction 动画块只能解决 CALayer 相干动画,无奈正确处理 UIView 的动画,甚至 UIView 的 Root layer(与 UIView 相关联的 CALayer)也不行。
UIView 的 Root layer 动画为什么会在 CATransaction 动画块中生效?
隐式动画的查找过程如下:

禁止隐式动画:

咱们把扭转属性时 CALayer 主动利用的动画称作行为,当 CALayer 的属性被批改时候,它会调用 -actionForKey: 办法,传递属性的名称。剩下的操作都在 CALayer 的头文件中有具体的阐明,本质上是如下几步:

    • 图层首先检测它是否有委托,并且是否实现 CALayerDelegate 协定指定的 -actionForLayer:forKey 办法。如果有,间接调用并返回后果。
    • 如果没有委托,或者委托没有实现 -actionForLayer:forKey 办法,图层接着查看蕴含属性名称对应行为映射的 actions 字典。

    如果 actions 字典没有蕴含对应的属性,那么图层接着在它的 style 字典接着搜寻属性名。

    • 最初,如果在 style 外面也找不到对应的行为,那么图层将会间接调用定义了每个属性的规范行为的 -defaultActionForKey: 办法。

    所以一轮残缺的搜寻完结之后,-actionForKey: 要么返回空(这种状况下将不会有动画产生),要么是 CAAction 协定对应的对象,最初 CALayer 拿这个后果去对先前和以后的值做动画。

    于是这就解释了 UIKit 是如何禁用隐式动画的:每个 UIView 对它关联的图层都表演了一个委托,并且提供了-actionForLayer:forKey 的实现办法。当不在一个动画块的实现中,UIView 对所有图层行为返回 nil,然而在动画 block 范畴之内,它就返回了一个非空值。

    • UIView 关联的图层禁用了隐式动画,对这种图层做动画的惟一方法就是应用 UIView 的动画函数(而不是依赖 CATransaction),或者继承 UIView,并笼罩 -actionForLayer:forKey: 办法,或者间接创立一个显式动画。
    • 对于独自存在的图层,咱们能够通过实现图层的 -actionForLayer:forKey: 委托办法,或者提供一个 actions 字典来管制隐式动画。

    参考资料 iOS Actions

    工夫零碎

    参考谈谈 iOS Animation

    CAMediaTiming 协定定义了在一段动画内用来管制逝去工夫的属性的汇合。CALayer 通过 CAMediaTiming 协定实现了一个有层级关系的工夫零碎。

    几个重要属性(都是 CALayer 的属性):

    • beginTime 是绝对于父级对象的开始工夫
    • timeOffset 是 active local time 的偏移量
    • speed 设置以后对象的工夫流逝绝对于父级对象工夫流的流逝速度
    • fillMode 决定了以后对象过了非 active 时间段的行为

    显示动画

    当须要对非 Root Layer 进行动画或者须要对动画做更多的自定义的行为的时候,须要应用显示动画,基类为 CAAnimation

    外围动画类中能够间接应用的类有:

    • CABasicAnimation
    • CAKeyframeAnimation
    • CATransition
    • CAAnimationGroup
    • CASpringAnimation

    CABasicAnimation 有三个比拟重要的属性,fromValue,toValue,byValue, 这三个属性都是可选的, 但不能同时多于两个为非空. 最终都是为了确定 animation 变动的终点和起点. 两头的值都是通过插值形式计算出来的. 插值计算的后果由 timingFunction 指定, 默认 timingFunction 为 nil, 会应用 liner 的, 也就是变动是平均的.

    1. 外围动画类的外围办法

    • 初始化 CAAnimation 对象

      • 个别应用 animation 办法生成实例 let animation = CABasicAnimation()
      • 如果是 CAPropertyAnimation 的子类,能够应用 ’let animation = CABasicAnimation(keyPath: String?)’ 来生成
    • 设置动画的相干属性

      • 执行工夫
      • 执行曲线
      • keyPath 的目标值
      • 代理等
    animation.duration = 2.0
    //        animation.fromValue = UIColor.blackColor()
            animation.toValue = NSValue(CGPoint: CGPointMake(300, 300))
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            animation.removedOnCompletion = false
            animation.fillMode = kCAFillModeForwards
    • 动画的增加和移除

      • 调用 CALayer 的 view2.layer.addAnimation(animation, forKey: "color")
      • 进行动画 view2.layer.removeAnimationForKey(String)view2.layer.removeAllAnimations()

    避免动画完结后回到初始状态

    只需设置 removedOnCompletion、fillMode 两个属性就能够了。

    transformAnima.removedOnCompletion = NO;
    transformAnima.fillMode = kCAFillModeForwards;

    解释:为什么动画完结后返回原状态?

    给一个视图增加 layer 动画时,真正挪动并不是咱们的视图自身,而是 presentation layer 的一个缓存。动画开始时 presentation layer 开始挪动,原始 layer 暗藏,动画完结时,presentation layer 从屏幕上移除,原始 layer 显示。这就解释了为什么咱们的视图在动画完结后又回到了原来的状态,因为它基本就没动过。
    这个同样也能够解释为什么在动画挪动过程中,咱们为何不能对其进行任何操作。
    所以在咱们实现 layer 动画之后,最好将咱们的 layer 属性设置为咱们最终状态的属性,而后将 presentation layer 移除掉。

    2. 外围动画类的罕用属性

    • KeyPath:能够指定 KeyPath 为 CALayer 的属性值,并对它批改,留神局部属性是不反对动画的
    • duration:动画的持续时间
    • repeatCount: 动画的反复次数
    • timingFunction:动画的工夫节奏管制
    • fillMode:视图在非 Active 时的行为
    • removedOnCompletion:动画执行结束后是否从图层上移除,默认为 YES(视图会复原到动画前的状态),可设置为 NO(图层放弃动画执行后的状态,前提是 fillMode 设置为 kCAFillModeForwards)
    • beginTime:动画提早执行工夫(通过 CACurrentMediaTime() + your time 设置)
    • delegate:代理
    func animationDidStart(anim: CAAnimation)
     func animationDidStop(anim: CAAnimation, finished flag: Bool)

    Timing Function 对应的类是 CAMediaTimingFunction, 它提供了两种取得工夫函数的形式, 一种是应用预约义的五种工夫函数, 一种是通过给点两个控制点失去一个工夫函数. 相干的办法为

    CAMediaTimingFunction(name: String)
    CAMediaTimingFunction(controlPoints: Float, c1y: Float, c2x: Float, c2y: Float)

    五种预约义的工夫函数名字的常量变量别离为

    • kCAMediaTimingFunctionLinear,
    • kCAMediaTimingFunctionEaseIn,
    • kCAMediaTimingFunctionEaseOut,
    • kCAMediaTimingFunctionEaseInEaseOut,
    • kCAMediaTimingFunctionDefault

    自定义的 Timing Function 的函数图像就是一条三次的贝塞尔曲线。

    CAKeyframeAnimation 动画

    两个决定动画关键帧的属性:

    • values: 关键帧数组对象,外面每一个元素就是一个关键帧,动画会在相应时间段内,顺次执行数组中每一个关键帧动画
    • path: 动画门路对象,能够指定一个门路,在执行动画时会沿着门路挪动,path 只能对 CALayer 的 anchorPoint 和 position 属性起作用
    • keyTimes: 设置关键帧对应的工夫点。范畴 0 ~ 1,默认每一帧工夫平分,keyTimes 数组中的每个元素定义了相应的 keyframe 的持续时间值作为动画的总持续时间的一小部分,每个元素的值必须大于、或等于前一个值。keyframeAni.keyTimes = [0.1,0.5,0.7,0.8,1]
    • calculationMode 计算模式,其次要针对的是每一帧的内容为一个座标点的状况, 也就是对 anchorPoint 和 position 进行的动画,示意插值计算的模式

      • kCAAnimationLinear 默认值 直线相连来差值
      • kCAAnimationDiscrete 离散的,不进行插值计算,所有关键帧一一显示
      • kCAAnimationPaced 动画平均的,此时 keytimes 和 timeFunctions 有效
      • kCAAnimationCubic 对关键帧为坐标点的关键帧进行圆滑曲线相连后插值计算, 对于曲线的形态还能够通过 tensionValues,continuityValues,biasValues 来进行调整自定义
      • kCAAnimationCubicPaced 在 kCAAnimationCubic 的根底上使得动画运行变得平均, 就是零碎工夫内静止的间隔雷同, 此时 keyTimes 以及 timingFunctions 也是有效的.

    简略例子

    CATransition

    转场动画,比 UIView 的转场动画具备更多的动画成果。

    CATransition 的属性:

    • type: 过渡动画的类型

      • kCATransitionFade 突变
      • kCATransitionMoveIn 笼罩
      • kCATransitionPush 推出
      • kCATransitionReveal 揭开

      公有动画类型的值有:”cube”、”suckEffect”、”oglFlip”、“rippleEffect”、”pageCurl”、”pageUnCurl” 等等

    • subtype: 过渡动画的方向

      • kCATransitionFromRight 从左边
      • kCATransitionFromLeft 从右边
      • kCATransitionFromTop 从顶部
      • kCATransitionFromBottom 从底部

    CASpringAnimation

    CASpringAnimation 是 iOS9 新退出动画类型,是 CABasicAnimation 的子类,用于实现弹簧动画。

    CASpringAnimation 的重要属性:

    • mass:品质(影响弹簧的惯性,品质越大,弹簧惯性越大,静止的幅度越大)
    • stiffness:弹性系数(弹性系数越大,弹簧的静止越快)
    • damping:阻尼系数(阻尼系数越大,弹簧的进行越快)
    • initialVelocity:初始速率(弹簧动画的初始速度大小,弹簧静止的初始方向与初始速率的正负统一,若初始速率为 0,示意疏忽该属性)
    • settlingDuration:结算工夫(依据动画参数估算弹簧开始静止到进行的工夫,动画设置的工夫最好依据此工夫来设置)
       private func springAni() {let ani = CASpringAnimation(keyPath: "bounds")
            ani.mass = 10.0 // 品质,影响图层静止时的弹簧惯性,品质越大,弹簧拉伸和压缩的幅度越大
            ani.stiffness = 5000 // 刚度系数(劲度系数 / 弹性系数),刚度系数越大,形变产生的力就越大,静止越快
            ani.damping = 100.0// 阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,进行越快
            ani.initialVelocity = 5.0// 初始速率,动画视图的初始速度大小; 速率为负数时,速度方向与静止方向统一,速率为正数时,速度方向与静止方向相同
            ani.duration = ani.settlingDuration
            ani.toValue = NSValue(CGRect: view4.bounds)
            ani.removedOnCompletion = false
            ani.fillMode = kCAFillModeForwards
            ani.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            view2.layer.addAnimation(ani, forKey: "boundsAni")
            
        }

    CAAnimationGroup

    应用 Group 能够将多个动画合并一起退出到层中,Group 中所有动画并发执行,能够不便地实现须要多种类型动画的场景,group 动画以数组示意。

    private func groupAni() {let posAni = CABasicAnimation(keyPath: "position")
        posAni.toValue = NSValue(CGPoint: CGPoint(x: 310, y: 400))
        let boundAni = CABasicAnimation(keyPath: "bounds")
        boundAni.toValue = NSValue(CGRect: CGRectMake(0, 0, 200, 200))
        let colorAni = CABasicAnimation(keyPath: "backgroundColor")
        colorAni.toValue = UIColor.redColor().CGColor
            
        let groupAni = CAAnimationGroup()
        groupAni.animations = [posAni, boundAni, colorAni]
        groupAni.duration = 1.5
        groupAni.fillMode = kCAFillModeForwards
        groupAni.removedOnCompletion = false
        groupAni.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        view1.layer.addAnimation(groupAni, forKey: "groupAni")
            
    }

    文中 demo 的地址:Github 动画 demo

    正文完
     0