Skip to content

5.2_实现 animatableData 计算属性

深入理解 animatableData

Animatable 协议的核心在于 animatableData 计算属性。它允许您将自定义视图的任何可动画属性转换为 SwiftUI 可以理解和插值的单一 VectorArithmetic 类型。这真是太棒了!🚀

当您想要为自定义视图添加动画时,animatableData 是您的秘密武器。它充当了视图状态和动画系统之间的桥梁。您会发现,掌握它能让您的动画效果提升一个档次。

如何实现 animatableData

实现 animatableData 属性需要您将视图中所有需要动画的属性打包成一个 VectorArithmetic 类型。通常,这会是 CGFloatAnimatablePair。例如,如果您有一个自定义的 Shape,并且想要动画化它的某个半径,您可以这样做:

swift
struct MyCircle: Shape, Animatable {
    var radius: CGFloat

    var animatableData: CGFloat {
        get { radius }
        set { radius = newValue }
    }

    func path(in rect: CGRect) -> Path {
        // ... 绘制路径 ...
    }
}

这使得 radius 属性能够平滑地进行动画过渡。是不是很简单?✨

处理多个可动画属性

当您的视图有多个需要动画的属性时,AnimatablePair 就派上用场了。它允许您将两个 VectorArithmetic 类型组合在一起。想象一下,您有一个自定义视图,既要动画化宽度,又要动画化高度:

swift
struct MyRectangle: View, Animatable {
    var width: CGFloat
    var height: CGFloat

    var animatableData: AnimatablePair<CGFloat, CGFloat> {
        get { AnimatablePair(width, height) }
        set {
            width = newValue.first
            height = newValue.second
        }
    }

    var body: some View {
        Rectangle()
            .frame(width: width, height: height)
            .foregroundColor(.blue)
    }
}

通过 AnimatablePair,您可以轻松地同时动画化 widthheight。这种灵活性让您能够创建极其复杂的动画效果。

animatableData 的幕后原理

当 SwiftUI 执行动画时,它会在动画的起始值和结束值之间对 animatableData 进行插值。例如,如果 radius 从 10 动画到 100,SwiftUI 会在动画过程中计算出 10 到 100 之间的所有中间值。

  • 插值过程: SwiftUI 会在每一帧更新 animatableData 的值。
  • 视图重绘: 每次 animatableData 更新时,视图都会根据新的值进行重绘。
  • 平滑过渡: 这种连续的更新和重绘创造了平滑的动画效果。

这种机制确保了无论您的自定义属性多么复杂,只要它们能被表示为 VectorArithmetic 类型,就能实现流畅的动画。大约 90% 的自定义动画都依赖于此。这绝对是您动画工具箱中的必备技能!💪

本站使用 VitePress 制作