上一篇文章主要介绍了一下在SwiftUI中如何自定义Shape,本篇文章主要介绍Shape中的
一个关键的属性AnimatableData,它用于定义可以被动画化的数据。通过实现 Animatable 协议,可以让自定义视图或图形响应动画变化。
AnimatableData 是 Animatable 协议的一部分,它指定了哪些数据是可以进行动画处理的,而Shape协议继承了Animatable协议。
AnimatableData 是一个属性,通常是一个简单的数据类型(如 CGFloat 或 Double),或者是一个符合 VectorArithmetic 协议的类型。这个属性表示了视图或图形中那些需要被动画化的部分。当这些数据发生变化时,SwiftUI 会自动计算中间帧,从而创建平滑的动画效果。
要使用 AnimatableData,需要:
- 定义一个遵循
Shape的结构体,即自定义一个Shape。 - 实现
Animatable协议(默认已经实现),只需指定animatableData属性。
下面是一个示例,展示如何创建一个圆角矩形,其圆角大小可以通过动画改变:
struct AnimatableDataDemo: View {@State private var cornerRadius: CGFloat = 0var body: some View {AnimatableRoundedRectangle(cornerRadius: cornerRadius).frame(width: 200, height: 200).onTapGesture {withAnimation(.easeInOut(duration: 1.0).repeatForever()) {cornerRadius = cornerRadius == 0 ? 50 : 0}}}
}struct AnimatableRoundedRectangle: Shape {var cornerRadius: CGFloatvar animatableData: CGFloat {get { cornerRadius }set { cornerRadius = newValue }}func path(in rect: CGRect) -> Path {let path = Path(roundedRect: rect, cornerRadius: cornerRadius)return path}
}
在自定义动画AnimatableRoundedRectangle中,定义了cornerRadius属性,用于改变圆角大小,animatableData通过get和set方法对cornerRadius属性读取和赋值,这样就将这个cornerRadius属性标记为animatableData,当cornerRadius变化时,就会有动画了。
上面代码中对cornerRadius添加了动画,并且动画反复执行。

如果我们舍弃animatableData这块,不将cornerRadius进行标记为animatableData,如下:
struct AnimatableRoundedRectangle: Shape {var cornerRadius: CGFloatfunc path(in rect: CGRect) -> Path {let path = Path(roundedRect: rect, cornerRadius: cornerRadius)return path}
}
运行效果如下。

当点击后,图形的圆角立即变化了,但是没有执行动画。
通过使用 AnimatableData,可以指定哪些属性的变化应该被动画化。这使得创建复杂的自定义动画变得简单而直接,极大地增强了 UI 的交互性和视觉吸引力。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。
