Choppy CATextLayer动画:同时使用fontSize +位置

chi*_*uda 11 core-animation ios swift

我需要一个动画CATextLayerbounds.size.height,positionfontSize.当我将它们添加到a时CAAnimationGroup,文本会在动画期间抖动,就像这样:

https://youtu.be/HfC1ZX-pbyM

fontSize使用bounds.size.heightAND/OR 进行动画制作时,文本的跟踪值(字符间距)的抖动似乎发生了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)
Run Code Online (Sandbox Code Playgroud)

我的设备运行的是iOS 11.0.


编辑2

我已经逐帧分解了每个动画(fontSize仅限和fontSize+ position).在每个视频中,我一次进行1帧.

fontSize唯一的视频(https://youtu.be/DZw2pMjDcl8)中,每个帧都会增加fontSize,因此没有波动.

fontSize+ position视频(https://youtu.be/_idWte92F38)中,position每帧都会更新,但不会fontSize.fontSize60%的帧只有增加,这意味着fontSize没有动画同步position,导致感知斩波.

所以,也许正确的问题是:为什么fontSize动画中的每一帧时,它的加入层中唯一的动画,而不是在作为部分附加CAAnimationGroup与结合position动画?

chi*_*uda 6

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

与此同时,我将用于将重绘与设备的刷新率CADisplayLink同步CATextLayer.fontSize,这将fontSize在每个帧中重新绘制适当的图层.


编辑

经过CADisplayLink一天左右的修补后,绘制到正确的fontSize证明是困难的,特别是当与自定义计时功能配对时.所以,我CATextLayer完全放弃了,然后又回去了UILabel.

使用UIKit的WWDC'17高级动画中,Apple推荐"视图变形"以在两个标签状态之间设置动画 - 即两个视图的平移,缩放和不透明度混合.UIViewPropertyAnimator为此提供了很多灵活性,例如混合多个计时功能和擦洗.视图变形对于在2个text值之间转换而非必须淡出文本表示,更改text和淡入时也很有用.

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

  • 你能给出一个代码示例吗? (2认同)