iOS进阶4 -- 动画总结

1.基础:逐帧 与 关键帧

逐帧动画:
类似于手绘翻页方式,我们可以将这个水杯在每帧画面中的位置一一找出来,这样实现动画的方式就叫作 逐帧动画,我们需要处理动画中的每一帧。

我们一般在计算机上用 FPS ( Frames Per Second) ,即 每秒的帧数 来表示动画的刷新速度,基于屏幕的刷新率等其他原因,在计算机上一般采用 60 FPS。
如果运动变化幅度较缓,减半到 30 FPS 时,我们肉眼也是可接受的。
较低的 FPS 会让我们有“卡顿”的感觉。

关键帧动画:
一个涉及数学和物理的问题:一个杯子初始位置在左边,n秒后匀速运动到右边,那么在每 1/60 秒的时候,这个杯子的位置显然是可以计算出来的了。
所以,我们其实只需要指定一些 关键 信息就能让计算机自己计算出每一帧杯子的位置了:

起始位置,比如一个坐标 (0,0)
结束位置,再比如一个坐标 (100,0)
动画总时间,比如 0.25 秒
匀速运动
这种方式就称之为 关键帧动画。即我们只需要给定几个关键帧的画面信息,关键帧与关键帧之间的过渡帧都将由计算机自动生成。

这里说的 关键帧动画,是指的广义上的一种动画制作方式,并不仅指 CAKeyframeAnimation,CABasicAnimation的实现方式也属于 关键帧动画

2.iOS 动画

一个动画的本质,就是动画对象(这里是 UIView)的状态,基于时间变化的反应了。简单说,就是给定任意一个时刻,如果你都能得到这个动画对象的位置和、形状等等属性,你就能实现这个动画了。
属性值的变化,既可能是位置、透明度、旋转角度等的变化,也包括形状的改变,比如从一条直线变化成一个圆圈,目标就是要得到变化过程中特定时刻的中间态。

iOS 的动画分为两大类:
系统提供的 关键帧动画 实现方式;用户指定 关键 信息,系统实现动画过程,对用户而言操作起来会简单些。
逐帧动画 实现方式;用户自己 画 出每一帧画面,系统操作方法简单,但用户操作的工作量就会大一些。

逐帧方法绘制:

简单的说,要实现逐帧的方式,就是需要 周期性 的调用 绘制 方法,绘制每帧的动画对象。

这里说的 绘制,不光是指覆写 UIView 的 - drawRect:的方法来手动重绘视图,也包括修改 UIView 它的属性,比如位置、颜色等。

iOS 的动画都是基于 CALayer 的,iOS 的 UIView 背后都有一个对应的 CALayer 。对 UIView 的修改实际上都是对背后 CALayer 的修改。
但如果在逐帧绘制的方法中修改了一个自建的 CALayer,这个 CALayer 不是对应某个 UIView 的,需注意系统的 隐式动画 的影响,后面会提到这点。

用逐帧方法绘制的原理不是很麻烦,麻烦的是绘制过程。
对于一个复杂动画,你可能需要运用各种物理、几何知识去计算视图中间状态的信息。
比如要实现一条直线卷曲变化为一个圆的动画,你就需要计算出中间态的曲线的弯曲程度和位置。

著名的 facebook 的 pop 动画框架,就是使用 CADisplayLink 这种逐帧绘制的方式实现的。

关键帧动画实现方式:
用 UIView 移动的简单例子。这里面有两个关键帧,起始帧和结束帧,除此之外还有2个关键信息:

起始帧,变化信息:坐标为 (0,0)
结束帧,变化信息:坐标为 (100,0)
动画时间,0.25秒
匀速运动
坐标 信息是 UIView 的一个属性(实际是对应到 CALayer 的属性),在动画实现里,我们只需要指定起始和结束的两个关键值就够了,中间的过渡值都有系统自动生成。
这里出现了两种值,一个是我们设定的,一个是系统生成的,所以要先在这里插入一个 模型层 和 展现层 的概念了

CALayer 的同一个属性值,会分别保存在模型层 modelLayer ,和展现层 presentationLayer 中。当我们修改属性值时,是修改的模型层的数值,动画时系统根据模型层的变化,生成的过渡值,是保存在展现层中的。

在 CALayer 的对象里能直接访问到这两层的信息。
而 CALayer 的底层实现实际不止这两层,但我们现在讨论动画的时候,可以只关心这两层。

在整个动画过程中,呈现出来的过程是这样的:
动画前,显示模型层的当前值;
动画开始,切换显示展现层的值;
动画过程中,展现层的值根据时间变化,我们看到的实际是展现层的值在变化;
动画结束,切换回显示模型层的值,此时模型层的值应被修改为动画结束时的值。
用一段代码来解释下动画过程。

 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    view.backgroundColor = [UIColor redColor];
    [self.view addSubview:view];

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(50, 0)];
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(150, 0)];
    [view.layer addAnimation:animation forKey:nil];

//    view.frame = CGRectOffset(view.frame, 100, 0);

你会发现动画结束后,view 又跳回了原来的位置,这是因为最后一行代码注释了,而这行代码的功能就是实现第4步,将模型层的值修改为动画结束时的值。

动画实现

代码中的 CABasicAnimation 就是真正的动画实现部分,也就是设定关键帧信息的地方。

将动画加入 CALayer 的代码定义为:

- (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key

接受的类型是 CAAnimation 类型,有下面这些子类:

CABasicAnimation,可设定起始结束两个关键帧的信息。
CAKeyframeAnimation,除首尾外,还可添加多个中间关键点。
CAAnimationGroup ,可组合多个动画,因为上面两种动画一次只能设置一个属性值。
CATransition,图层过渡动画,默认是淡入。比如修改一个 CALayer的背景色时,是从初始色慢慢淡入过渡到结束色。
可修改为新颜色把旧颜色顶出去等效果。还可使用 CIFilter 滤镜做过渡效果,一些开源 UIViewController 的过渡动画使用了这种方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值