浅汇-iOS 动画

        在iOS开发中,制作动画效果是最让开发者享受的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,吸引他们的眼光 —— 这对于app而言是非常重要的。我们总是追求更为酷炫的实现,如果足够仔细,我们不难发现一个好的动画通过步骤分解后本质上不过是一个个简单的动画实现。本文就个人搜集的一些动画相关的理论和实践知识做个小结,不足之处请勿见怪。


理论

      UIView只是CALyer之上的封装,更准确的来说,UIView是CALyer的简版封装,加上事件处理的集合类。CALayer是QuartzCore库内的类,是iOS上最基本的绘制单元。其次,我们知道iOS平台的Cocoa Touch 是源于OS X平台的Cocoa),是在Cocoa的基础上添加了适用于移动手机设备的手势识别、动画等特性;但从底层实现上来说,Cocoa Touch与Cocoa共用一套底层的库,其中就包括了QuartCore.framework;但QuartCore.framework一开始就是为OS X设计的,所以其中有部分特性是不适合做移动设备开发的,比如最重要的坐标系统。因此,我们也就不难理解为何UIView/NSView在CALayer上做了一层封装。

基于UIView实现的动画

简单的Block动画

[UIView animateWithDuration:0.2 animations:^{  }]; [UIView animateWithDuration:0.5f animations:^{  } completion:^(BOOL finished) { //    }];

UIView [begin commit]

_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50); [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:1.0f]; _demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50); [UIView commitAnimations];

弹性动画

[UIView animateWithDuration:0.8 delay:0  usingSpringWithDamping:0.5 initialSpringVelocity:6  options:UIViewAnimationOptionCurveEaseOut animations:^{  // } completion:^(BOOL finished) {  }];    //参数:持续时间,延迟时间,阻尼系数,初始速度

关键帧动画(中间可以添加合适多的帧来做不同的衔接动画)

UIView animateKeyframesWithDuration:3.f delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{ [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.8 animations:^{ // }]; [UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:1.6 animations:^{ // }];                                                              } completion:^(BOOL finished) { //                              }];

CALayer动画

值得注意的是  CASpringAnimation 是 CABasicAnimation 的子类用于实现弹性动画的效果。

常用属性

duration : 动画的持续时间

beginTime : 动画的开始时间

repeatCount : 动画的重复次数

autoreverses : 执行的动画按照原动画返回执行

timingFunction : 控制动画的显示节奏系统提供五种值选择,

分别是:

kCAMediaTimingFunctionLinear 线性动画

kCAMediaTimingFunctionEaseIn 先慢后快(慢进快出)

path:关键帧动画中的执行路径

type : 过渡动画的动画类型,系统提供了四种过渡动画。

kCATransitionFade 渐变效果

kCATransitionMoveIn 进入覆盖效果

subtype : 过渡动画的动画方向

kCATransitionFromRight 从右侧进入

kCATransitionFromLeft 从左侧进入

基础动画主要提供了对于CALayer对象中的可变属性进行简单动画的操作。比如:位移、透明度、缩放、旋转、背景色等等。

重要属性

fromValue : keyPath对应的初始值

toValue : keyPath对应的结束值

基础动画(CABaseAnimation)

0:1  1:0  实现下拉剪头的展开和收起

CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; rotationAnimation.duration = 0.3f; rotationAnimation.repeatCount = 1; rotationAnimation.autoreverses = NO; rotationAnimation.fromValue = [NSNumber numberWithFloat: beginValue*M_PI]; rotationAnimation.toValue = [NSNumber numberWithFloat:endValue*M_PI]; rotationAnimation.removedOnCompletion = NO; rotationAnimation.fillMode = kCAFillModeForwards; rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [pinLayer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];

关键帧动画(CAKeyframeAnimation

CAKeyframeAnimation和CABaseAnimation都属于CAPropertyAnimatin的子类。`CABaseAnimation只能从一个数值(fromValue)变换成另一个数值(toValue),而CAKeyframeAnimation则会使用一个NSArray保存一组关键帧。 `

重要属性

values : 就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path : 可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略。

keyTimes : 可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的。

组合动画:

CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"]; NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)]; NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)]; NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)]; NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)]; NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)]; NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)]; anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil]; //缩放动画 CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; anima2.fromValue = [NSNumber numberWithFloat:0.8f]; anima2.toValue = [NSNumber numberWithFloat:2.0f]; //旋转动画 CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; anima3.toValue = [NSNumber numberWithFloat:M_PI*4]; //组动画 CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil]; groupAnimation.duration = 4.0f; [_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];

过渡动画(CATransition) 多数为私有的API使用后`无法上架app`。

私有API提供了其他很多非常炫的过渡动画,比如@”cube”、@”suckEffect”、@”oglFlip”、 @”rippleEffect”、@”pageCurl”、@”pageUnCurl”、@”cameraIrisHollowOpen”、@”cameraIrisHollowClose”等。

粒子动画

transform动画

transform是一个非常重要的属性,它在矩阵变换的层面上改变视图的显示效果,完成旋转、形变、平移等等操作。在它被修改的同时,视图的frame也会被真实改变。有两个数据类型用来表示transform,分别是CGAffineTransform和CATransform3D。前者作用于UIView,后者为layer层次的变换类型。基于后者可以实现更加强大的功能。

对于想要了解矩阵变换是如何作用实现的,可以参考这篇博客:CGAffineTransform 放射变换

在开始使用transform实现你的动画之前,我先介绍几个常用的函数:

/// 用来连接两个变换效果并返回。返回的t = t1 * t2 CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2) /// 矩阵初始值。[ 1 0 0 1 0 0 ] CGAffineTransformIdentity /// 自定义矩阵变换,需要掌握矩阵变换的知识才知道怎么用。参照上面推荐的原理链接 CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty) /// 旋转视图。传入参数为 角度 * (M_PI / 180)。等同于 CGAffineTransformRotate(self.transform, angle) CGAffineTransformMakeRotation(CGFloat angle) CGAffineTransformRotate(CGAffineTransform t, CGFloat angle) /// 缩放视图。等同于CGAffineTransformScale(self.transform, sx, sy) CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy) /// 缩放视图。等同于CGAffineTransformTranslate(self.transform, tx, ty) CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty) 特殊地,transform属性默认值为CGAffineTransformIdentity,可以在形变之后设置该值以还原到最初状态 样例 self.demoImageView.transform = CGAffineTransformIdentity;

transform严格的说不是一种动画,而是动画中的一部分操作,我拿出来说是因为它同时出现在了UIView 动画和CALayer动画中。

一些应用

- 利用上面CALayer 基础动画的代码实现下拉剪头的展开和收起,还可以实现时钟指针的旋转

  pinLayer = [CALayer layer]; [pinLayer setBounds:CGRectMake(0, 0, 14, 8)]; [pinLayer setContents:(id)[UIImage imageNamed:@"downArrow.png"].CGImage]; [pinLayer setPosition:CGPointMake(305*NEWX,20)]; [pinLayer setAnchorPoint:CGPointMake(0.5, 0.5)]; [behindBgView.layer addSublayer:pinLayer];

输入框在输入错误信息时的摇晃效果

利用CAShapeLayer 和CABasicAnimation 可以实现加载动画

iOS渲染视图的层级图

- UIKit:最常用的视图框架,封装度最高,都是OC对象

- CoreAnimation:提供强大的2D和3D动画效果

- CoreGraphics:主要绘图系统,常用于绘制自定义视图,纯C的API,使用Quartz2D做引擎

- CoreImage:给图片提供各种滤镜处理,比如高斯模糊、锐化等

- OpenGL-ES:主要用于游戏绘制,但它是一套编程规范,具体由设备制造商实现

更多内容可以点击(iOS开发UI篇---iOS Core Animation 总结)


小结

事实告诉我们动画是要靠设计的,你看我上面的动画抽的一笔,但事实上用同样的代码可以写出很漂亮的动画。

一篇很棒的动画总结文章

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 浅汇-iOS UI布局

      iOS中UI的布局是很重要的,而在前期开发中就要选定好布局的方法,因为这对整个工程乃至于后期的版本维护都有很重要的影响。本文从比较老的Frame到新生Aut...

    進无尽
  • iOS开发专题分类大全(简书iOS学习资源大收录!)

    为了更好地将简书上面的iOS文章分类,以方便我们日后的集中式强化学习,这里整理了二十多个专题以供大家查阅!

    陈满iOS
  • ios动画

    在iOS开发中,动画是提高用户体验重要的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,这对于app而言是非常重要的。 简介 iOS动画主要是指C...

    xiangzhihong
  • 苹果系统编程必看书籍

    1.iOS Core Animation: Advanced Techniques ? 很全面的解释了Core Animation,动画原理说得很浅显易懂,结合...

    程序员互动联盟
  • React Native 学习资源精选仓库

    React Native Awesome汇集了各类react-native学习资料、工具、组件、开源App、资源下载、以及相关新闻等,只求精不求全。 如果你是...

    CrazyCodeBoy
  • 【阅读清单】有奖内测体验活动

    完成了内测体验的小伙伴,可以填写问卷,活动结束后我们将统一进行审核,审核结束就进行礼品发放。问卷链接:https://wj.qq.com/s2/7433898/...

    云加社区
  • 从案例出发,由浅到深了解 iOS 动画

    iOS 的动画框架很成熟,提供必要的信息,譬如动画的起始位置与终止位置,动画效果就出来了

    猿_人类
  • iOS动画总结

    在iOS开发中,动画是提高用户体验重要的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,这对于app而言是非常重要的。 简介 iOS动画主要是指C...

    xiangzhihong
  • iOS动画(补充)--特殊Layer动画

    iOS中有一些特殊的layer,也可以做一些动画效果,本文就补充两个可以做动画效果的layer: CAEmitterLayer 和 CAReplicatorLa...

    Haley_Wong

扫码关注云+社区

领取腾讯云代金券