iOS动画(一):拍电影与CABasicAnimation
2016-04-26 21:48
591 查看
声明:本文是本人 编程小翁 原创,转载请注明。
动效设计一直是iOS平台的优势,良好的动效设计可以很好地提升用户体验。而动画则是动效的基础支撑。本动画系列将从易到难逐步分析,本文就是第一站:CABasicAnimation。
通过本文,你能收获到:
以拍电影的思路写动画代码
编写自己的简单动画库
这个部分你需要了解以下概念: CALayer、CAAnimation、拍电影(R U kidding me?)
CALayer是个与UIView很类似的概念,同样有backgroundColor、frame等相似的属性,我们可以将UIView看做一种特殊的CALayer。但实际上UIView是对CALayer封装,在CALayer的基础上再添加交互功能。UIView的显示必须依赖于CALayer。
我们同样可以跟新建view一样新建一个layer,然后添加到某个已有的layer上,同样可以对layer调整大小、位置、透明度等。
一般来说,layer可以有两种用途:一是对view相关属性的设置,包括圆角、阴影、边框等参数,更详细的参数请点击这里;二是实现对view的动画操控。因此对一个view进行动画,本质上是对该view的.layer进行动画操纵。
在iOS中Core Animation层的动画是依赖CAAnimation类实现的。这里提到一个概念,那就是Core Animation层动画。没错,既然有所谓的Core Animation层动画那就应该有其他层动画。看下面的图:
1.png
在iOS的不同图形层次中都可以写动画代码。越上层,封装程度越高,动画实现越简洁越简单,但是自由度越低;反之亦然。本系列着重介绍Core Animation层的基本动画实现方案。
CAAnimation可以分为以下几类:
1.CABasicAnimation
基础动画,通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
关键帧动画,可定制度比CABasicAnimation高,也是本系列的接下来的内容
3.CAAnimationGroup
组动画,支持多个CABasicAnimation或者CAKeyframeAnimation动画同时执行
4.CATransition 这个就是苹果帮开发者封装好的一些动画
本文作为系列的第一篇文章,先从最简单的CABasicAnimation说起。
此刻你心里估计在想:What the f**k? 但其实实现CABasicAnimation动画的过程与拍电影的流程非常类似:
准备演员--->CALayer,规定电影的主角是谁
准备剧本--->CAAnimation,规定电影该怎么演,怎么走,怎么变换
开拍--->AddAnimation,开始执行
唯一的不同估计是电影里演员很重要,颜值担当那是必须的,只要颜值够高,狗血剧本也很受欢迎。但对于基础动画,演员没太大作用,关键是剧本要好要硬。也就是CABasicAnimation要足够精彩。
不扯淡了,进入下一部分。
按照上面的解释,要想实现一个类似图2中蓝色方块的心跳效果就需要这么做:
step1: 准备演员(CALayer初始化)
step2: 准备剧本(配置CABasicAnimation)
step3: 开演
图2.gif
代码中有几个参数需要解释一下:
keyPath: 决定基础动画的类型,该值不能随便取,一旦取错就达不到想要的效果。要改变位置就取
fromValue: 动画的起始状态值,虽然iOS文档给出的类型是
autoreverse: 当动画执行到toValue指定的状态时是从toValue的状态逆回去,还是直接跳到fromValue的状态再执行一遍
fileMode: fillMode的作用就是决定当前对象过了非active时间段的行为. 非active时间段是指动画开始之前以及动画结束之后。如果是一个动画CAAnimation,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用. 下面来讲各个fillMode的意义:
kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态。因为有可能出现fromValue不是目前layer的初始状态的情况,如果fromValue就是layer当前的状态,则这个参数就没太大意义。
kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.
表1.png
接下来我们来看一下怎么实现多个动画同时执行,这里会用到上面提到的CAAnimationGroup类。我们的目标是实现图2中最底下的紫色方块的动画,缩放、移动、旋转同时进行。
这时候你可以再回想一下拍电影的过程:
演员,CALayer对象
剧本,这时候就需要准备CAAnimationGroup来当剧本了,剧本由诸如缩放、移动等小剧本合成。
开演,addAnimation
直接看剧本的代码:
缩放:
移动:
旋转:
你也注意到了,你可以认为其实每个小剧本都是独立的,他们之间唯一的联系就是一起被放到GroupAnimation中:
最后把整合后的大剧本groupAnimation交给导演开拍:
这样动画就会自动执行。
从第二节我们知道,实现基本动画最重要的要有一个CABasicAnimation。于是乎,我们可以用一个工具类或者类扩展提前写好一些动画类型(剧本),返回值是CABasicAnimation对象。每想到一种新的动画类型就可以往里面加,逐渐形成自己动画代码库。比如这样:
图3 动画库举例.png
要用的时候直接取来用:
图4 动画库应用举例.png
以上代码取自我的一份开源的角标库一句话实现badge效果,动画库文件是
动效设计一直是iOS平台的优势,良好的动效设计可以很好地提升用户体验。而动画则是动效的基础支撑。本动画系列将从易到难逐步分析,本文就是第一站:CABasicAnimation。
通过本文,你能收获到:
以拍电影的思路写动画代码
编写自己的简单动画库
一、概念
这个部分你需要了解以下概念: CALayer、CAAnimation、拍电影(R U kidding me?)
1、CALayer
CALayer是个与UIView很类似的概念,同样有backgroundColor、frame等相似的属性,我们可以将UIView看做一种特殊的CALayer。但实际上UIView是对CALayer封装,在CALayer的基础上再添加交互功能。UIView的显示必须依赖于CALayer。我们同样可以跟新建view一样新建一个layer,然后添加到某个已有的layer上,同样可以对layer调整大小、位置、透明度等。
一般来说,layer可以有两种用途:一是对view相关属性的设置,包括圆角、阴影、边框等参数,更详细的参数请点击这里;二是实现对view的动画操控。因此对一个view进行动画,本质上是对该view的.layer进行动画操纵。
2、CAAnimation
在iOS中Core Animation层的动画是依赖CAAnimation类实现的。这里提到一个概念,那就是Core Animation层动画。没错,既然有所谓的Core Animation层动画那就应该有其他层动画。看下面的图:1.png
在iOS的不同图形层次中都可以写动画代码。越上层,封装程度越高,动画实现越简洁越简单,但是自由度越低;反之亦然。本系列着重介绍Core Animation层的基本动画实现方案。
CAAnimation可以分为以下几类:
1.CABasicAnimation
基础动画,通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
关键帧动画,可定制度比CABasicAnimation高,也是本系列的接下来的内容
3.CAAnimationGroup
组动画,支持多个CABasicAnimation或者CAKeyframeAnimation动画同时执行
4.CATransition 这个就是苹果帮开发者封装好的一些动画
本文作为系列的第一篇文章,先从最简单的CABasicAnimation说起。
3、拍电影
此刻你心里估计在想:What the f**k? 但其实实现CABasicAnimation动画的过程与拍电影的流程非常类似:准备演员--->CALayer,规定电影的主角是谁
准备剧本--->CAAnimation,规定电影该怎么演,怎么走,怎么变换
开拍--->AddAnimation,开始执行
唯一的不同估计是电影里演员很重要,颜值担当那是必须的,只要颜值够高,狗血剧本也很受欢迎。但对于基础动画,演员没太大作用,关键是剧本要好要硬。也就是CABasicAnimation要足够精彩。
不扯淡了,进入下一部分。
二、开始拍电影
按照上面的解释,要想实现一个类似图2中蓝色方块的心跳效果就需要这么做:step1: 准备演员(CALayer初始化)
CALayer *scaleLayer = [[CALayer alloc] init]; scaleLayer.backgroundColor = [UIColor blueColor].CGColor; scaleLayer.frame = CGRectMake(60, 20 + kYOffset, 50, 50); scaleLayer.cornerRadius = 10; [self.view.layer addSublayer:scaleLayer]; [scaleLayer release];//MRC下
step2: 准备剧本(配置CABasicAnimation)
//设定剧本 CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale”];//keyPath不能填错,有特定被选值 scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0]; scaleAnimation.toValue = [NSNumber numberWithFloat:1.5]; scaleAnimation.autoreverses = YES; scaleAnimation.fillMode = kCAFillModeForwards; scaleAnimation.removedOnCompletion = NO; scaleAnimation.repeatCount = MAXFLOAT; scaleAnimation.duration = 0.8;
step3: 开演
[scaleLayer addAnimation:scaleAnimation forKey:@"scaleAnimation”];
图2.gif
代码中有几个参数需要解释一下:
keyPath: 决定基础动画的类型,该值不能随便取,一旦取错就达不到想要的效果。要改变位置就取
position,要改变透明度就取
opacity,要等比例缩放就取
transform.scale...更多key请看下面的表1,要尽量能记住这些内容
fromValue: 动画的起始状态值,虽然iOS文档给出的类型是
id,不过这里应该传
NSValue对象,比如NSNumber(NSNubmer继承自NSValue)。其具体含义
autoreverse: 当动画执行到toValue指定的状态时是从toValue的状态逆回去,还是直接跳到fromValue的状态再执行一遍
fileMode: fillMode的作用就是决定当前对象过了非active时间段的行为. 非active时间段是指动画开始之前以及动画结束之后。如果是一个动画CAAnimation,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用. 下面来讲各个fillMode的意义:
kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态。因为有可能出现fromValue不是目前layer的初始状态的情况,如果fromValue就是layer当前的状态,则这个参数就没太大意义。
kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.
表1.png
接下来我们来看一下怎么实现多个动画同时执行,这里会用到上面提到的CAAnimationGroup类。我们的目标是实现图2中最底下的紫色方块的动画,缩放、移动、旋转同时进行。
这时候你可以再回想一下拍电影的过程:
演员,CALayer对象
剧本,这时候就需要准备CAAnimationGroup来当剧本了,剧本由诸如缩放、移动等小剧本合成。
开演,addAnimation
直接看剧本的代码:
缩放:
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0]; scaleAnimation.toValue = [NSNumber numberWithFloat:1.5]; scaleAnimation.autoreverses = YES; scaleAnimation.repeatCount = MAXFLOAT; scaleAnimation.duration = 0.8;
移动:
CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; moveAnimation.fromValue = [NSValue valueWithCGPoint:groupLayer.position]; moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(320 - 80, groupLayer.position.y)]; moveAnimation.autoreverses = YES; moveAnimation.repeatCount = MAXFLOAT; moveAnimation.duration = 2;
旋转:
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"]; rotateAnimation.fromValue = [NSNumber numberWithFloat:0.0]; rotateAnimation.toValue = [NSNumber numberWithFloat:6.0 * M_PI]; rotateAnimation.autoreverses = YES; rotateAnimation.repeatCount = MAXFLOAT; rotateAnimation.duration = 2;
你也注意到了,你可以认为其实每个小剧本都是独立的,他们之间唯一的联系就是一起被放到GroupAnimation中:
CAAnimationGroup *groupAnnimation = [CAAnimationGroup animation]; groupAnnimation.duration = 2; groupAnnimation.autoreverses = YES; groupAnnimation.animations = @[moveAnimation, scaleAnimation, rotateAnimation]; groupAnnimation.repeatCount = MAXFLOAT;
最后把整合后的大剧本groupAnimation交给导演开拍:
[groupLayer addAnimation:groupAnnimation forKey:@"groupAnnimation”];
这样动画就会自动执行。
三、编写自己的动画库
从第二节我们知道,实现基本动画最重要的要有一个CABasicAnimation。于是乎,我们可以用一个工具类或者类扩展提前写好一些动画类型(剧本),返回值是CABasicAnimation对象。每想到一种新的动画类型就可以往里面加,逐渐形成自己动画代码库。比如这样:图3 动画库举例.png
要用的时候直接取来用:
图4 动画库应用举例.png
以上代码取自我的一份开源的角标库一句话实现badge效果,动画库文件是
CAAnimation+WAnimation.h,欢迎
star哦。
相关文章推荐
- iOS 集成环信(一)
- 编译型语言和解释型语言的区别
- 从今天起,开始记录学习IOS的点点滴滴。
- ios开发之使用pch文件
- VS2015 Xamarin- ios程序真机调试
- iOS开发--assign、retain、copy的区别
- iOS自定义TabBar使用popToRootViewControllerAnimated重叠问题解决
- ios高级课之---数据处理之文件读写1
- iOS:在使用Cocoapods安装shareSDK时出现的link路径错误
- iOS 写入文件保存数据的方式
- iOS开发--多线程编程(二)NSThread买票
- iOS开发点滴-添加阴影效果
- iOS LLDB调试精解
- iOS8新特性之交互式通知
- iOS dSYM文件结构剖析(上)
- iOS Crash文件的解析(一)
- iOS单元测试GHUnit + OCMock(使用cocoapods版)
- iOS基础:获取资源文件的方法
- iOS开发-你真的会用SDWebImage?(转发)
- IOS+openCV在Xcode的入门开发