Layer Animation
2020-04-23 本文已影响0人
ienos
默认情况下, Layer的大部分标准属性都可以执行动画, 无论是添加一个 CAAnimation 到 Layer (显示动画),还是为属性指定一个动作然后修改它(隐式动画)
接下来, 将讨论如何子类化 CALayer 并添加我们自己的属性, 让它执行相应的动画. 因为可能涉及到以下需求:
1.修改一个属性,间接动画一个或者多个标准属性
2.修改一个属性,触发 Layer 的重绘方法
3.去除标准属性的隐式动画效果
一、间接动画
在非动画属性的 setter 方法里面,改变一个或者多个动画属性的值
二、去除隐式动画
( 1 ) 重写 layer 方法
- (id<CAAction>)actionForKey:(NSString *)event {
// if ([event isEqualToString:@"position"]) {
// return nil;
// }
}
( 2 ) 在改变属性时调用
[CATransaction begin]; //开启事务
[CATransaction setDisableActions:YES]; //禁用隐式动画
layer.frame = CGRectOffset(layer.frame, 100, 0);
能显式的关闭这个事务中的 action 查询操作。
关闭了查询也就是关闭了动画效果,属性值的变化就会立即生效,而没有动画效果了
[CATransaction commit]; //提交事务
三、自定义属性, 通过 setter 方法触发 Layer 的重绘方法(也可用于非可视化属性的动态变化 )
( 1 ) 在.h文件添加对象类型属性, 并在@implementation
里面设置该属性为@dynamic definition
- CALayer 具有为任何被声明成dynamic的属性生成 setter 和 getter 的能力
- dynamic 告诉编译器, 属性的 setter 和 getter 方法由用户自己实现, 不自动生成
- 编译通过, 若调用 setter、getter 方法且用户无自定义将会造成崩溃
( 2 ) 让 CALayer 监控自定义的属性, 使得自定义属性在发生改变时, 调用 - dispaly
和 -actionForKey
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:@"definition"]) {
return true;
}
return [super needsDisplayForKey:key];
}
( 3 ) 给自定义的属性添加动态变化的效果
- (id<CAAction>)actionForKey:(NSString *)event {
// 给自定义的属性添加动态变化的效果
// 该方法是在赋值之前调用, 所以在无初始值的情况下, 第一次display 为 nil , 将会造成无动画效果(解决方法: 附期望的初值)
// fromValue : 这里的 modelLayer 和 presentationLayer 的值相同
if ([event isEqualToString:@"definition"]) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.fromValue = self.definition;
return animation;
}
return [super actionForKey:event];
}
( 4 ) 在- display
里面调用重绘方法
- (void)display {
// 当设置某个 CALayer 的某个属性, 实际上设置的是 modelLayer 的值
// modelLayer 表示正在进行的动画结束时, layer所到达的最终状态
// presention Layer 是 modelLayer 的拷贝, 但它所表示的是当前值, 中间动画状态的值
// 在这里调用重绘方法
NSLog(@"display, definition: %@", [[self presentationLayer] definition]);
}