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

( 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]);
}
上一篇下一篇

猜你喜欢

热点阅读