CABasicAnimation

2021-06-17  本文已影响0人  今天写明天改

背景

展示个提示,像跑马灯. 最近要做这样的事情。乍一看,简单,但是:

做法

跑马灯,本质上就是一个位移动画,那自然是CABasicAnimation 和它的封装UIView.animate,本文主要看看CABasicAnimation

首先指定需要动画的属性

let positionAnimation = CABasicAnimation(keyPath:"position.x")

然后设置起始值和终止值

positionAnimation.fromValue = 0

positionAnimation.toValue = -leftOffset

最后是设置时间将动画加到label上

positionAnimation.duration = duration

label.layer.add(positionAnimation, forKey: animKey)

跑起来,发现看到的效果总是不对。文字并不是从制定的位置开始运动的

找问题

既然是看到的效果不对,那就看看负责显示动画的presentation layer层的位置是什么样子的

我们在每次执行动画前打印看一下:

label.layer.presentation()?.frame, 这是它的presentationLayer的frame

多次运行动画得到如下结果

rame: Optional((0.0, 0.0, 23.0, 9.0))

frame: Optional((-337.5139744877815, 0.0, 525.0, 9.0))

frame: Optional((-270.14062067866325, 0.0, 433.0, 9.0))

frame: Optional((-510.49657133221626, 0.0, 751.0, 9.0))

frame: Optional((-306.79565209150314, 0.0, 525.0, 9.0))

frame: Optional((-235.69693331420422, 0.0, 433.0, 9.0))

frame: Optional((-403.153050519526, 0.0, 751.0, 9.0))

frame: Optional((-282.75428069382906, 0.0, 525.0, 9.0))

frame: Optional((-177.64594815671444, 0.0, 341.0, 9.0))

frame: Optional((-236.20260278880596, 0.0, 433.0, 9.0))

frame: Optional((-462.53013302385807, 0.0, 751.0, 9.0))

可以看到当动画开始的时候负责显示的presentation layer的位置并不是0,这样处理的结果是,每次我们的跑马灯都是从左侧很远的地方开始滚动,不是我们想要的效果 

自然我的第一个想法:就是开始动画前把动画都移除掉

positionAnimation.fillMode = .forwards

label.layer.removeAllAnimations()

但是发现不行,动画依然是从label中间某个位置开始运动

于是猜想是每次动画开始时label的实际的位置不对,我开始修改每次的起始位置,每次动画前手动将label的位置置为0,每次结束后,将label的位置复原;还找是不是每次动画还没有结束就开始新动画导致动画叠加导致的.然而都没有得到正确结果。

怎么办,只能看看现有的跑马灯是怎么做的,于是我在之前大神写的代码里发现了某个和我一样(比我高级多了的代码)里发现了跑马灯

发现转机

代码中是使用这样的方式:

将动画的kaypath变为transform.translation: 

CABasicAnimation(keyPath:"transform.translation")

这个时候,我们需要将fromValue 和toValue都设置成 NSValue对象,对象里包含的是一个NSSize 或者 CGSize 的数据类型.用来表示x 和 y 坐标轴的转换. 

同样,我们两个维度的变换可以变成一个维度的,也就是说keyPath设置成transform.translation.x也行。只是对应的fromValue 和toValue 设置成NSNumber对象。

毕竟是大神,用这样的代码,动画正常了,每次都从最左侧开始运动了。

这两种方式下每次启动动画的时候也不需要移除之前的动画。例如不需要以下的代码

label.layer.removeAllAnimations()

当然因为是跑马灯所以填充模式和是否移除这两句话也不需要了

animation.fillMode = .forwards

animation.isRemovedOnCompletion = false

原因

话说回来: position.x 和transform.translation有什么区别

参考官方文档

CATransform3D Key Paths

You can use the enhanced key path support to retrieve specific transformation values for a property that contains a CATransform3D data type. To specify the full key path for a layer’s transforms, you would use the string value transform or sublayerTransform followed by one of the field key paths in Table C-2. For example, to specify a rotation factor around the layer’s z axis, you would specify the key path transform.rotation.z. 

CGPoint Key Paths

If the value of a given property is a CGPoint data type, you can append one of the field names in Table C-3 to the property to get or set that value. For example, to change the x component of a layer’s position property, you could write to the key path position.x. 

对于我的整个label的运动来说,动画是加在layer层的,我的位移用的也是整个frame的位移,不是一个点。所以应该使用translation来指定动画的属性

上一篇 下一篇

猜你喜欢

热点阅读