显式动画

本文深入探讨了Core Animation中的属性动画,包括显式动画CABasicAnimation和CAKeyframeAnimation的使用方法,以及如何通过代理实现动画结束的回调。此外还介绍了关键路径动画背后的机制和虚拟属性的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  • 属性动画

CAAnimationDelegate在任何头文件中都找不到,但是可以在CAAnimation头文件或者苹果开发者文档中找到相关函数。

当更新属性的时候,我们需要设置一个新的事务,并且禁用图层行为。否则动画会发生两侧,一个是因为显式的CABasicAnimation,另一次是因为隐式动画(关于隐式动画后面我会介绍)。

例如我们更改主视图的背景颜色:

CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"backgroundColor";
    animation.toValue = (__bridge id)color.CGColor;
    animation.delegate = self;
    //apply animation to layer
    [self.view.layer addAnimation:animation forKey:nil];
// 显式动画结束时调用。
- (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag { //set the backgroundColor property to match animation toValue [CATransaction begin]; [CATransaction setDisableActions:YES]; self.colorLayer.backgroundColor = (__bridge CGColorRef)anim.toValue; [CATransaction commit]; }
使用代理时回调动画结束函数,要判断是哪个图层调用的。
注意:动画本身会作为一个参数传入委托的方法,也许你会认为可以控制器中把动画存储为一个属性,
然后回调比较,但是实际上并不起作用,因为委托传入的动画参数是原始值的深拷贝,
从而不是同一个值。
但当真正跑在iOS设备上时,我们发现在-animationDidStop:finished:委托方法调用之前,
指针会迅速返回到原始值,问题在于回调方法在动画完成之前已经被调用了,但不能保证这发生在属性动画
返回初始状态之前。这同时也很好地说明了为什么要在真实的设备上测试动画代码,而不仅仅是模拟器。

  • 关键帧动画

CABasicAnimation揭示了大多数隐式动画背后依赖的机制,这的确很有趣,但是显式地给图层添加CABasicAnimation相较于隐式动画而言,只能说费力不讨好。


CAKeyframeAnimation是另一种UIKit没有暴露出来但功能强大的类。和CABasicAnimation类似,CAKeyframeAnimation同样是CAPropertyAnimation的一个子类,它依然作用于单一的一个属性,但是和CABasicAnimation不一样的是,它不限制于设置一个起始和结束的值,而是可以根据一连串随意的值来做动画。


关键帧起源于传动动画,意思是指主导的动画在显著改变发生时重绘当前帧(也就是关键帧),每帧之间剩下的绘制(可以通过关键帧推算出)将由熟练的艺术家来完成。CAKeyframeAnimation也是同样的道理:你提供了显著的帧,然后Core Animation在每帧之间进行插入。

CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"backgroundColor";
    animation.duration = 2.0;
    animation.values = @[
                         (__bridge id)[UIColor blueColor].CGColor,
                         (__bridge id)[UIColor redColor].CGColor,
                         (__bridge id)[UIColor greenColor].CGColor,
                         (__bridge id)[UIColor blueColor].CGColor ];
    [self.colorLayer addAnimation:animation forKey:nil];
注意到序列中开始和结束的颜色都是蓝色,这是因为CAKeyframeAnimation并不能自动把当前值作为第一帧(就像CABasicAnimation那样把fromValue设为nil)。动画会在开始的时候突然跳转到第一帧的值,然后在动画结束的时候突然恢复到原始的值。所以为了动画的平滑特性,我们需要开始和结束的关键帧来匹配当前属性的值。

还可以使用贝塞尔曲线绘制曲线路径,然后沿着路径运动。
通过rotationMode自动对齐图层到曲线
  • 虚拟属性

之前提到过属性动画实际上是针对于关键路径而不是一个键,这就意味着可以对子属性甚至是虚拟属性做动画。但是虚拟属性到底是什么呢?

考虑一个旋转的动画:如果想要对一个物体做旋转的动画,那就需要作用于transform属性,因为CALayer没有显式提供角度或者方向之类的属性

toValue = [NSValue valueWithCATransform3D: CATransform3DMakeRotation(M_PI, 0, 0, 1)];
使用NAValue指定结构体类型值,byValue是叠加变换。一般我们使用

transform.rotation关键路径应用动画,而不是transform本身。
transform.rotation而不是transform做动画的好处如下:
  1. 我们可以不通过关键帧一步旋转多于180度的动画。
  2. 可以用相对值而不是绝对值旋转(设置byValue而不是toValue)。
  3. 可以不用创建CATransform3D,而是使用一个简单的数值来指定角度。
  4. 不会和transform.position或者transform.scale冲突(同样是使用关键路径来做独立的动画属性)。

transform.rotation属性有一个奇怪的问题是它其实并不存在。这是因为CATransform3D并不是一个对象,它实际上是一个结构体,也没有符合KVC相关属性,transform.rotation实际上是一个CALayer用于处理动画变换的虚拟属性。

你不可以直接设置transform.rotation或者transform.scale,他们不能被直接使用。当你对他们做动画时,Core Animation自动地根据通过CAValueFunction来计算的值来更新transform属性。

CAValueFunction用于把我们赋给虚拟的transform.rotation简单浮点值转换成真正的用于摆放图层的CATransform3D矩阵值。你可以通过设置CAPropertyAnimationvalueFunction属性来改变,于是你设置的函数将会覆盖默认的函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值