上一篇文章主要介绍了一下在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 = 0
var 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: CGFloat
var 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: CGFloat
func path(in rect: CGRect) -> Path {
let path = Path(roundedRect: rect, cornerRadius: cornerRadius)
return path
}
}
运行效果如下。
当点击后,图形的圆角立即变化了,但是没有执行动画。
通过使用 AnimatableData
,可以指定哪些属性的变化应该被动画化。这使得创建复杂的自定义动画变得简单而直接,极大地增强了 UI 的交互性和视觉吸引力。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。