ios - 断断续续的 CATextLayer 动画 : fontSize + position concurrently

标签 ios swift core-animation

我需要为 CATextLayer 制作动画的 bounds.size.height , position , 和 fontSize .当我将它们添加到 CAAnimationGroup 时, 文字在动画中抖动,就像这样:

https://youtu.be/HfC1ZX-pbyM

文本的跟踪值(字符之间的间距)的抖动似乎在动画时发生 fontSizebounds.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

我逐帧分解了每个动画(仅 fontSizefontSize + position )。在每个视频中,我一次前进一帧。

fontSize仅视频 ( https://youtu.be/DZw2pMjDcl8 ),每一帧 都会增加 fontSize ,所以没有波涛汹涌。

fontSize + position视频 ( https://youtu.be/_idWte92F38 ), position在每一帧更新,但不是fontSize 。只增加了fontSize在 60% 的帧中,这意味着 fontSize动画与 position 不同步,导致感知到的斩波。

所以也许正确的问题是:为什么 fontSize当它是添加到图层的唯一动画时在每一帧中进行动画处理,但当作为 CAAnimationGroup 的一部分添加时则不进行动画处理结合 position动画?

最佳答案

Apple DTS 认为此问题是一个错误。已提交报告。

与此同时,我将使用 CADisplayLinkCATextLayer.fontSize 的重绘与设备的刷新率同步,这将重绘图层在每一帧中适当的fontSize


编辑

在对 CADisplayLink 进行了大约一天的修改之后,绘制到正确的 fontSize 证明是困难的,尤其是在与自定义计时功能配对时。因此,我将完全放弃 CATextLayer,并返回到 UILabel

在 WWDC '17's Advanced Animations with UIKit , Apple 建议使用“ View 变形”在两个标签状态之间制作动画——即两个 View 的平移、缩放和不透明度混合。 UIViewPropertyAnimator 为此提供了很大的灵 active ,例如混合多个计时功能和擦洗。 View 变形对于在 2 个 text 值之间转换也很有用,而无需淡出文本表示、更改 text 和淡入。

我确实希望 Apple 可以加强 CATextLayer 对非交互式动画的支持,因为我更喜欢使用一个 View 来为相同的文本表示设置动画。

关于ios - 断断续续的 CATextLayer 动画 : fontSize + position concurrently,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46700859/

相关文章:

ios - 正确屏蔽 CALayers

iOS - UICollectionView 设置为 0 后单元格之间仍然有间距

ios - 放大用户位置 - Swift

swift - 将.xib文件内TableCellView中项目的outlet设置为自定义NSTableCellView子类

ios - 带圆点的动画线图

cocoa-touch - CALayer 中的抗锯齿绘图

iOS 7 UISearchDisplayController 问题

android - Flutter - 当我运行 print(myFile.absolute.path) 时,myFile 不在范围内

ios - Skobbler SKMapView 和 UIPanGestureRecognizer

swift - 使用 tvOS 强制触摸