我需要为CATextLayer
bounds.size.height
,position
和fontSize
制作动画。当我将它们添加到CAAnimationGroup
时,文本会在动画期间抖动,就像这样:
在使用fontSize
和/或bounds.size.height
设置position
动画时,似乎会出现文本跟踪值(字符间距)的抖动。我已经孤立fontSize
,并且它自身表现良好。
如果我同时为边界和字体大小设置动画,如何防止文本在CATextLayer
中抖动?
修改
我已经开始动画bounds
了。现在,我只关心fontSize
+ position
。以下是两个显示差异的视频。
fontSize
(流畅):https://youtu.be/FDPPGF_FzLI
fontSize
+ position
(紧张):https://youtu.be/3rFTsp7wBzk
这是代码。
let startFontSize: CGFloat = 16
let endFontSize: CGFloat = 30
let startPosition: CGPoint = CGPoint(x: 40, y: 100)
let endPosition: CGPoint = CGPoint(x: 20, y: 175)
// Initialize the layer
textLayer = CATextLayer()
textLayer.string = "Hello how are you?"
textLayer.font = UIFont.systemFont(ofSize: startFontSize, weight: UIFont.Weight.semibold)
textLayer.fontSize = startFontSize
textLayer.alignmentMode = kCAAlignmentLeft
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.contentsScale = UIScreen.main.scale
textLayer.isWrapped = true
textLayer.backgroundColor = UIColor.lightGray.cgColor
textLayer.anchorPoint = CGPoint(x: 0, y: 0)
textLayer.position = startPosition
textLayer.bounds.size = CGSize(width: 450, height: 50)
view.layer.addSublayer(textLayer)
// Animate
let damping: CGFloat = 20
let mass: CGFloat = 1.2
var animations = [CASpringAnimation]()
let fontSizeAnim = CASpringAnimation(keyPath: "fontSize")
fontSizeAnim.fromValue = startFontSize
fontSizeAnim.toValue = endFontSize
fontSizeAnim.damping = damping
fontSizeAnim.mass = mass
fontSizeAnim.duration = fontSizeAnim.settlingDuration
animations.append(fontSizeAnim)
let positionAnim = CASpringAnimation(keyPath: "position.y")
positionAnim.fromValue = textLayer.position.y
positionAnim.toValue = endPosition.y
positionAnim.damping = damping
positionAnim.mass = mass
positionAnim.duration = positionAnim.settlingDuration
animations.append(positionAnim)
let animGroup = CAAnimationGroup()
animGroup.animations = animations
animGroup.duration = fontSizeAnim.settlingDuration
animGroup.isRemovedOnCompletion = true
animGroup.autoreverses = true
textLayer.add(animGroup, forKey: nil)
我的设备正在运行iOS 11.0。
编辑2
我已逐帧细分了每个动画(仅限fontSize
,fontSize
+ position
)。在每个视频中,我一次进行1帧。
在仅fontSize
视频(https://youtu.be/DZw2pMjDcl8)中,每一帧会使fontSize
增加,因此不会出现波动。
在fontSize
+ position
视频(https://youtu.be/_idWte92F38)中, position
会在每一帧中更新,但不会更新fontSize
。 60%的帧中只有fontSize
有所增加,这意味着fontSize
不会与position
同步动画,从而导致感知斩波。
所以也许正确的问题是:为什么fontSize
在每一帧中设置动画,因为它是添加到图层的唯一动画,而不是作为CAAnimationGroup
的一部分与...一起添加时position
动画?
答案 0 :(得分:6)
Apple DTS认为此问题是一个错误。报告已经提交。
与此同时,我将使用CADisplayLink
将CATextLayer.fontSize
的重绘同步到设备的刷新率,这将使用适当的fontSize
重新绘制图层在每一帧中。
修改强>
在修补CADisplayLink
一天左右之后,绘制到正确的fontSize
证明是困难的,尤其是在与自定义计时功能配对时。所以,我完全放弃CATextLayer
并回到UILabel
。
在WWDC' 17' Advanced Animations with UIKit中,Apple建议"查看变形"在两个标签状态之间设置动画 - 即两个视图的平移,缩放和不透明度混合。 UIViewPropertyAnimator
为此提供了很多灵活性,例如混合多个计时功能和擦洗。视图变形对于在2个text
值之间转换而非必须淡出文本表示,更改text
和淡入淡出也很有用。
我希望Apple可以加强CATextLayer
对非交互式动画的支持,因为我更喜欢使用一个视图来动画相同的文本表示。