iOS 动画一览

作者: 豆志昂扬 | 来源:发表于2017-04-09 17:12 被阅读81次

    1. 为什么动画

    在移动互联网的时代,移动应用的竞争不再局限于内容与技术层面,用户体验方面在愉悦用户方面越来越重要。 良好的动画效果可以让用户得到清晰的反馈、以及在复杂场景下不易迷失等好处,可以说动画是构建良好用户体验不可缺失的一环。

    iOS上的动画效果主要覆盖以下几个角度:

    • 视图的移动,缩放,旋转, 褪色, 加速度(Velocity),阻力(Damp);
    • 渐变, 不规则形状 + 蒙版图层;
    • 粒子效果;
    • 3D动画;
    • 视图切换动画;

    iOS平台上实现动画效果有多种技术选择,�如UIKit框架内的UIView、Graphics & Animation框架内的CoreAnimation。这些丰富的图形与动画技术框架是iOS平台上实现各种动画效果的基础。 第三方也有诸如Facebook的Pop动画引擎,甚至有些应用会使用OpenGL、SpriteKit、Metal等游戏引擎来实现复杂的动画效果。

    2. UIView - �动画

    iOS 在UIKit - UIView里封装了一些方便开发者的动画API,功能强大。
    从下面的例子可以看到通过暴露的接口可以设置哪些属性。

    UIView.animate(withDuration: 0.5, 
                              delay: 0.5, 
                              usingSpringWithDamping: 0.4,
                               initialSpringVelocity: 0.4, 
                              options: UIViewAnimationOptions.curveLinear, 
                             animations: {
                                        //TODO
                            }, completion: nil)
    //Transition
    UIView.transition(from: UIView,
                          to: UIView,
                          duration: TimeInterval,
                          options: UIViewAnimationOptions,
                          completion: ((Bool) -> Void)?)
    //KeyFrame
    UIView.animateKeyframes(withDuration: TimeInterval,
                           delay: TimeInterval,
                           options: UIViewKeyframeAnimationOptions,
                          animations: { 
                            //Add frame changes
                           UIView.addKeyframe(withRelativeStartTime: Double,
                                  relativeDuration: Double,
                                  animations: { 
                                     //TODO
                             })
            },
              completion: <((Bool) -> Void)?)
    

    3. CALayer 动画

    CAAnimation的类图
    //允许对单个layer添加多个无相互依赖的动画
    let flyRight = CABasicAnimation(keyPath: "position.x") 
    flyRight.fromValue = -view.bounds.size.width/2 
    flyRight.toValue = view.bounds.size.width/2 
    flyRight.duration = 0.5
    flyLeft.repeatCount = 4
    flyLeft.autoreverses = true
    flyLeft.speed = 2.0  
    //CABasicAnimation 是纯对象,Copy对象。
    heading.layer.addAnimation(flyRight, forKey: "infoappear")
    //移除 animation
    info.layer.removeAnimationForKey("infoappear")
    
    //CAAnimationGroup 可以让多个无依赖动画同步进行
    
    //CAKeyframeAnimation 对于keyframeAnimation on UIView
    let wobble = CAKeyframeAnimation(keyPath: "transform.rotation") wobble.duration = 0.25
    wobble.repeatCount = 4
    //注意这里的values是数组类型
    wobble.values = [0.0, -M_PI_4/4, 0.0, M_PI_4/4, 0.0] wobble.keyTimes = [0.0, 0.25, 0.5, 0.75, 1.0] heading.layer.addAnimation(wobble, forKey: nil)
    
    //CAShapeLayer + UIBezierPath
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame         = showView.bounds;                // 与showView的frame一致
    layer.strokeColor   = [UIColor greenColor].CGColor;   // 边缘线的颜色
    layer.fillColor     = [UIColor clearColor].CGColor;   // 闭环填充的颜色
    layer.lineCap       = kCALineCapSquare;               // 边缘线的类型
    layer.path          = path.CGPath;                    // 从贝塞尔曲线获取到形状
    layer.lineWidth     = 4.0f;                           // 线条宽度
    layer.strokeStart   = 0.0f;
    layer.strokeEnd     = 0.1f;
    
    //CAGradientLayer是用来生成两种或更多颜色平滑渐变的。
    

    需要注意的是UIKit中UIBezierPath类可以创建基于矢量的路径。此类是Core Graphics框架关于CGPathRef数据的一个封装,使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

    CADisplayLink VS NSTimer

    • iOS设备的屏幕每秒会刷新60次,CADisplayLink在屏幕每次刷新时都会调用,精确度非常高,并且CADisplayLink的使用场合相对专一,适合做UI的不停重绘,比如动画的连续绘制。
    • NSTimer的使用范围则相对广泛,可以做单次或者循环处理某个任务,精度相比CADisplayLink要低。

    CALayer拥有presentLayer, modelLayer, 在动画运行的时候,用户看到的其实是presentLayer的变化。

    Core Animation相对UIView暴露的接口拥有更多灵活度和自由,可以在动画运行时监控和随时终止。

    如果遇到使用UIView或CALayer相关的接口都能实现的动画,建议使用UIView封装的API接口,因为UIView封装了CAlayer相关接口,使用和维护更简单。

    4. 3D 动画

    上面列举的都是2D范围内的动画,Core Animation也支持3D动画。但iOS中的3D动画本质上并不能算真正的3D, 而只是3D在二维平面上的投影。


    从上面图中,动画可以修改anchorPoint, position, bounds 和 frame。

    var imageTransform = CATransform3DIdentity
    //在某个transform3D变换的基础上进行平移变换,t是上一个transform3D,其他参数同上
    imageTransform = CATransform3DTranslate( imageTransform, 0.0, imageYOffset, 0.0)
    //x,y,z分别对应x轴,y轴,z轴的缩放比例
    imageTransform = CATransform3DScale( imageTransform, 0.95, 0.6, 1.0)
    //x,y,z决定了旋转围绕的中轴,取值为-1——1之间,例如(1,0,0),则是绕x轴旋转(0.5,0.5,0)
    imageTransform = CATransform3DRotate( imageTransform, CGFloat(M_PI_4/2), -1.0, 0.0, 0.0)
    image.layer.transform = imageTransform
    
    //CATransform3DMakeTranslation
    

    5. 粒子动画

    先来看张粒子效果图, 类似效果在游戏中经常看到。


    在QuartzCore框架中,CAEmitterLayer和CAEmitterCell可以帮助开发者轻松实现粒子效果。
    其中CAEmitterLayer继承自CALayer,可以将一个或多个CAEmitterCell添加到上面。

    CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
    //例子发射位置
    snowEmitter.emitterPosition = CGPointMake(120,20);
    //发射源的尺寸大小
    snowEmitter.emitterSize = CGSizeMake(self.view.bounds.size.width * 20, 20);
        //发射模式
        snowEmitter.emitterMode = kCAEmitterLayerSurface;
        //发射源的形状
        snowEmitter.emitterShape = kCAEmitterLayerLine;
        
        //创建雪花类型的粒子
        CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
        //粒子的名字
        snowflake.name = @"snow";
        //粒子参数的速度乘数因子
        snowflake.birthRate = 1.0;
        snowflake.lifetime = 120.0;
        //粒子速度
        snowflake.velocity =10.0;
        //粒子的速度范围
        snowflake.velocityRange = 10;
        //粒子y方向的加速度分量
        snowflake.yAcceleration = 2;
        //周围发射角度
        snowflake.emissionRange = 0.5 * M_PI;
        //子旋转角度范围
        snowflake.spinRange = 0.25 * M_PI;
        snowflake.contents = (id)[[UIImage imageNamed:@"snow"] CGImage];
        //设置雪花形状的粒子的颜色
        snowflake.color = [[UIColor colorWithRed:0.200 green:0.258 blue:0.543 alpha:1.000] CGColor];
        snowEmitter.shadowOpacity = 1.0;
        snowEmitter.shadowRadius = 0.0;
        snowEmitter.shadowOffset = CGSizeMake(0.0, 1.0);
        //粒子边缘的颜色
        snowEmitter.shadowColor = [[UIColor redColor] CGColor];
        snowEmitter.emitterCells = [NSArray arrayWithObjects:snowflake,,nil];
    

    6. View Controller转场动画

    iOS中除了常见的View Controller转场动画push/present外,iOS还支持开发者定制自有的转场动画效果。
    这时需要实现协议UIViewControllerAnimatedTransitioning,该协议内要实现两个方法:

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {}
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
      let containerView = transitionContext.containerView
      let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
      let fromView =  transitionContext.view(forKey: UITransitionContextViewKey.from)!
       ///要点在这里
    }
    
    

    而对应的ViewController要实现UIViewControllerTransitioningDelegate协议。

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      ///返回转场动画
      }
    
    ...
    

    更多阅读
    iOS Animations by Tutorials
    请关注豆志昂扬微信公众号获取更多内容:

    • 直接添加公众号豆志昂扬
    • 微信扫描下图二维码;

    相关文章

      网友评论

        本文标题:iOS 动画一览

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