iOS 动画一览

1. 为什么动画

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

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

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

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

iOS 动画一览_第1张图片

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 动画

iOS 动画一览_第2张图片
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在二维平面上的投影。

iOS 动画一览_第3张图片

从上面图中,动画可以修改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. 粒子动画

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

iOS 动画一览_第4张图片

在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 动画一览_第5张图片

你可能感兴趣的:(iOS 动画一览)