Trigger:动画的激活方式

到目前为止,我们已经见识了通过按钮点击触发的动画。其实,触发动画的方法不仅限于按钮点击。在本章中,您将学习多种不同的动画启动方式。

按钮(Button)

再回顾下按钮触发动作的方式,如下例:

Export-1713436215413.gif

通过「点击」按钮,改变「变量」,变量的改变导致了「可渐变属性」(比如Opacity、RotationEffect、ScaleEffect)跟着改变,最后通过.animation修饰符告知 SwiftUI,跟踪变量,计算「插值」,实现「动」画效果。

选择器(Picker)

Picker 组件常用于从一系列「选项」中进行「选择」,例如可以实现滑动视图的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
swift复制代码
@State var selection: Int = 0

VStack {
Picker("颜色", selection: $selection) {
Text("绿色").tag(0)
Text("红色").tag(1)
}.pickerStyle(.segmented)

ZStack {
Color.green
//当选中时,横坐标从 -500 移动到 0,反之从 0 到 -500
.offset(x: selection == 0 ? 0 : -500)
Color.red
//当选中时,横坐标从 500 移动到 0,反之从 0 到 500
.offset(x: selection == 1 ? 0 : 500)
}
}.animation(.easeIn, value: selection)
.padding()

Export-1713437121094.gif

滑块(Slider)

Slider 组件用于从连续值范围内选择一个值,例如可以增加一点动画的执行间隔,让动画有一点小小的滞后感:

1
2
3
4
5
6
swift复制代码HStack {
Color.orange.frame(width: state * 400)
Color.green
}.animation(.linear(duration: 3), value: state)

Slider(value: $state)

Export-1713438807287.gif

计步器(Stepper)

计数器可以「增减」数值,很容易与动画配合产生「值变」的动画效果,如下例:

1
2
3
4
5
6
7
8
9
10
11
swift复制代码ZStack {

ForEach(0..<100, id: \.self){index in

Circle().fill(.cyan.gradient.opacity(0.5)).frame(width: CGFloat.random(in: state...50)).position(x: CGFloat.random(in: state...300), y: CGFloat.random(in: state...600))

}

}.animation(.easeInOut, value: state)

Stepper("Stepper", value: $state)

Export-1713439125905.gif

出现后(On Appear)

onAppear常常应用于页面加载后执行一些初始化的动作或方法,用于动画时,常应用于开屏动画,例如:

1
2
3
4
swift复制代码View.onAppear() {
loading.toggle()
}
}

Export-1713440111879.gif

OnAppear_Intro.swift

消失后(On Disappear)

onAppear常常应用于页面关闭后执行一些销毁的动作或后置的方法,用于动画时,常应用于保存后的等待效果,例如:

1
2
3
swift复制代码View.onDisappear(){
refreshWhenFormDisappear = true
}

Export-1713441345966.gif

点击(TapGesture)

跟按钮(Button)有类似的用法,不过除了单击,它还是支持多次点击(比如双击)触发事件,例如双击放大或缩小:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
swift复制代码Circle()
.fill(.blue.gradient)
.frame(width: 150)
.overlay(content: {
Text("双击")
.font(.title)
.foregroundStyle(.white)
})
// 放大 2 倍
.scaleEffect(changed ? 2 : 1)
.animation(.easeIn, value: changed)
//监听「双击」事件
.onTapGesture(count: 2, perform: {
changed.toggle()
})

Export-1713441918894.gif

拖拽(DragGestures)

拖拽常用于将视图拖拽到一定的「程度」(超过某个值)后,触发一个动画事件,比如实现一个类似于 Sheet 的通过拖拽展开的效果:

1
2
3
4
5
6
7
8
swift复制代码View
.frame(height: offset > 500 ? 500 : offset < 200 ? 200 : offset)
.gesture(
DragGesture()
.onChanged({ value in
offset = offset - value.location.y
})
).animation(.easeIn, value: offset)

Export-1713443018373.gif

DragGesture_Intro.swift

缩放(MagnificationGesture)

通常用于图片的缩放,如下例:

1
2
3
4
5
6
7
8
9
10
swift复制代码  Image("demo")
.resizable()
.frame(width: 200, height: 200)
.scaleEffect(scale)
.gesture(MagnifyGesture()
.onEnded({ value in
//通过手势放大或缩小图片
scale = value.magnification
})
).animation(.linear, value: scale)

Export-1713443836885.gif

旋转(RotationGesture)

当给旋转事件添加动画后,会产生流畅的「转动」效果,如下例:

1
2
3
4
5
6
7
8
9
10
swift复制代码Image(systemName: "gear")
.font(.system(size: 200))
.foregroundStyle(.green)
.rotationEffect(.degrees(degree))
.animation(.linear, value: degree)
.gesture(RotateGesture()
.onEnded({ angle in
degree = degree + angle.rotation.degrees
})
)

Export-1713444173727.gif

滑动(ScrollView)

Export-1713445683857.gif

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
swift复制代码ScrollView {
ZStack {
GeometryReader(content: { geometry in
Image("mh")
.resizable()
.scaledToFill()
.offset(y: -geometry.frame(in: .global).origin.y * 0.5)
})

VStack(spacing: 50){
ForEach(0..<15, id: \.self){index in
RoundedRectangle(cornerRadius: 25.0)
.fill(.ultraThinMaterial)
.frame(width: 300, height: 100)

}
}
}
}.ignoresSafeArea()

这段代码中的动画效果是由 GeometryReaderoffset 的组合产生的。具体来说,这种动画效果是因为 offset 修饰符使用了 GeometryReader 提供的 geometry.frame(in: .global).origin.y 值来动态调整图片的 y 偏移量。这里逐步解释一下各个部分是如何工作的:

GeometryReader 的作用

  • GeometryReader 用于获取其内容当前的尺寸和位置。在这个例子中,它用来监控 Image 组件的全局位置(global 坐标空间)。
  • geometry.frame(in: .global).origin.y 表示 Image 在全局坐标空间中的 y 轴起始位置。当你滚动 ScrollView 时,这个值会改变,因为图像视图在屏幕上的位置在变化。

offset 修饰符的作用

  • offset(y: -geometry.frame(in: .global).origin.y * 0.5) 用于根据 GeometryReader 读取到的 y 坐标来动态设置图片的偏移。这里的 * 0.5 是一个缩放因子,意味着图片的滚动速度是滚动视图的一半。
  • 这种偏移方式常被用来创建视差滚动效果(parallax effect),即背景以比前景更慢的速度移动,从而增加深度感和动态效果。

动画效果的产生

  • ScrollView 被滑动时,geometry.frame(in: .global).origin.y 的值会随着滑动的距离发生变化。因此,Imageoffset 也会相应地动态改变。
  • 尽管这段代码没有显式添加动画修饰符(如 .animation()),滑动时图像位置的连续改变创建了一种平滑的视觉变化,看起来像是动画效果。这是由 SwiftUI 的渲染系统自动处理的,它优化了视图更新,使变化看起来平滑。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%