layer 动画解释笔记

来源:互联网 发布:网络电视怎么安装 编辑:程序博客网 时间:2024/05/18 23:12

一个个Layer通过tree的结构组织起来,在Display的过程中实际上有3种Layer tree。

  1. model layer tree (模型层树)

    我们通常意义说的Layer。当我们修改layer中的属性时,就会立刻修改model layer tree。

  2. presentation tree (表示层树)

    Layer在屏幕中的真实位置,或者说在动画的过程中,layer 的位置

  3. render tree (渲染树)

    apple的render server进程中,是真正处理动画的地方。而且线程的优先级也比我们主线程优先级高。所以有时候即使我们的App主线程busy,依然不会影响到手机屏幕的绘制工作

基本动画


CABasicAnimation 简单的为图层的属性提供修改。

场景,简单的位移动画

1
2
3
4
5
6
7
8
CABasicAnimation * animation = [CABasicAnimation animation];
animation.keyPath = @"position.x";
animation.fromValue = @77;
animation.toValue = @200;
animation.duration = 3;
[self.v.layer addAnimation:animation forKey:@"basic"];
self.v.layer.position = CGPointMake(200, 25);

多步动画


CAKeyframeAnimation 支持关键帧动画,你可以指定的图层属性的关键路径
动画,包括动画的每个阶段的价值,以及关键帧时间和计时功能的一系列值。在 动画运行是,每个值被特定的插入值替代。

场景 动画定义超过两个步骤。

1
2
3
4
5
6
7
8
9
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.x";
animation.values = @[ @0, @10, @-10, @10, @0 ];
animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
animation.duration = 0.4;
animation.additive = YES;
[form.layer addAnimation:animation forKey:@"shake"];
  1. values 数组定义了表单应该到哪些位置。
  2. 设置 keyTimes 属性让我们能够指定关键帧动画发生的时间。它们被指定为关键帧动画总持续时间的一个分数。我们看到是要去 5 个位置,就是 6 步操作,为了保证恒速,我们每 10pt 用 1/6 的keytime
  3. 设置 additive 属性为 YES 使 Core Animation 在更新presentation layer 之前将动画的值添加到 model layer 中去。这使我们能够对所有形式的需要更新的元素重用相同的动画,且无需提前知道它们的位置。因为这个属性从 CAPropertyAnimation 继承,所以你也可以在使用 CABasicAnimation 时使用它。 additive ,动画被设置成相对的。

沿路径动画

虽然用代码实现一个简单的水平晃动并不难,但是沿着复杂路径的动画就需要我们在关键帧的 values 数组中存储大量 box 化的 CGPoint。 值得庆幸的是,CAKeyframeAnimation 提供了更加便利的 path 属性作为代替。

1
2
3
4
5
6
7
8
9
10
11
12
CGRect boundingRect = CGRectMake(-150, -150, 300, 300);
CAKeyframeAnimation *orbit = [CAKeyframeAnimation animation];
orbit.keyPath = @"position";
orbit.path = CFAutorelease(CGPathCreateWithEllipseInRect(boundingRect, NULL));
orbit.duration = 4;
orbit.additive = YES;
orbit.repeatCount = HUGE_VALF;
orbit.calculationMode = kCAAnimationPaced;
orbit.rotationMode = kCAAnimationRotateAuto;
[satellite.layer addAnimation:orbit forKey:@"orbit"];
  1. CGPathCreateWithEllipseInRect(),创建一个椭圆形的不可改变的路径,我们创建一个圆形的 CGPath 作为我们的关键帧动画的 path。
  2. calculationMode 是控制关键帧动画时间的另一种方法。我们通过将其设置为 kCAAnimationPaced,让 Core Animation 向被驱动的对象施加一个恒定速度,不管路径的各个线段有多长。将其设置为 kCAAnimationPaced 将无视所有我们已经设置的 keyTimes。
  3. rotationMode 属性为 kCAAnimationRotateAuto 确保飞船沿着路径旋转。作为对比,如果我们将该属性设置为 nil 那动画会是什么样的呢

我个人更建议这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CGPoint arcCenter=CGPointMake(100,100); // 中心锚点
int radius = 100; // 半径
UIBezierPath * circlePath = [UIBezierPath bezierPathWithArcCenter:arcCenter
radius:radius startAngle:DEGREES_TO_RADIANS(-180)
endAngle:DEGREES_TO_RADIANS(180)
clockwise:YES];
CAKeyframeAnimation * orbit = [CAKeyframeAnimation animation];
orbit.keyPath = @"position";
orbit.path = circlePath.CGPath;
orbit.duration = 4;
orbit.additive = YES;
orbit.repeatCount = HUGE_VALF;
orbit.calculationMode = kCAAnimationPaced;
orbit.rotationMode = kCAAnimationRotateAuto;
[self.v.layer addAnimation:orbit forKey:@"orbit"];

bezierPathWithArcCenter 方法在 api 里写的很清楚,clockwise 为 YES 为顺时针,NO 为逆时针

同样,看图

时间函数

之前的动画都是匀速的,如何让动画更生动通过引入一个 时间函数 (timing function) (有时也被称为 easing 函数)来实现这个目标。该函数通过修改持续时间的分数来控制动画的速度。
最简单的 easing 函数是 linear。它在整个动画上维持一个恒定的速度。在 Core Animation 中,这个功能由 CAMediaTimingFunction 类表示。

1
2
3
4
5
6
7
8
9
10
11
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.x";
animation.fromValue = @50;
animation.toValue = @150;
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[rectangle.layer addAnimation:animation forKey:@"basic"];
rectangle.layer.position = CGPointMake(150, 0);

这部分不再细说,直接看 RBBAnimation, 它包含一个允许使用 更多复杂 easing 函数 的自定义子类 CAKeyframeAnimation

动画组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
CABasicAnimation *zPosition = [CABasicAnimation animation];
zPosition.keyPath = @"zPosition";
zPosition.fromValue = @-1;
zPosition.toValue = @1;
zPosition.duration = 1.2;
CAKeyframeAnimation *rotation = [CAKeyframeAnimation animation];
rotation.keyPath = @"transform.rotation";
rotation.values = @[ @0, @0.14, @0 ];
rotation.duration = 1.2;
rotation.timingFunctions = @[
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
];
CAKeyframeAnimation *position = [CAKeyframeAnimation animation];
position.keyPath = @"position";
position.values = @[
[NSValue valueWithCGPoint:CGPointZero],
[NSValue valueWithCGPoint:CGPointMake(110, -20)],
[NSValue valueWithCGPoint:CGPointZero]
];
position.timingFunctions = @[
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
];
position.additive = YES;
position.duration = 1.2;
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
group.animations = @[ zPosition, rotation, position ];
group.duration = 1.2;
// group.beginTime = 0.5; 这里如果设置了会出错,原文章设置
[card.layer addAnimation:group forKey:@"shuffle"];
card.layer.zPosition = 1;

一些属性

position

图层的 position 属性是一个 CGPoint 的值,它指定图层相当于它父图层的位置, 该值基于父图层的坐标系。
在不修改layer其他属性的情况下,layer.position = view.center
可看图

提到的其他有趣的文章

  1.  关于动画时间的一篇很棒的文章
  2.  CAShapeLayer路径动画

参考

  1. http://www.cocoachina.com/industry/20140701/8995.html

声明

  1. 这是一篇关于 http://objccn.io/issue-12-1/ 的学习笔记,概念大多copy原著,如有侵权,请联系本人删除。
0 0
原创粉丝点击