iOS SwiftUI 动画开发指南
为了把大家吸引过来,先上几张动画效果图:
"引狼图"1 :按钮点击 - 果冻动画效果

"引狼图"2 :波纹动画效果

"引狼图"3 :Lottie复杂动画效果

1、动画概念
SwiftUI 的动画是基于声明式的,当视图的状态发生变化时,系统会自动在旧状态和新状态之间插入中间帧,创建平滑的过渡效果。
工作原理:
状态驱动:动画由状态变化触发
声明式语法:描述"做什么"而不是"怎么做"
自动插值:系统自动计算中间值
类型安全:编译时检查动画兼容性
1.1、隐式动画
隐式动画通过 .animation() 修饰符自动应用于视图的所有可动画属性变化。当修饰符观察的值发生变化时,所有可动画的属性都会以指定的动画方式过渡。
隐式动画特点:
- 使用 .animation() 修饰符
- 状态变化时自动动画
- 代码简洁,声明式
swift
import SwiftUI
struct SimpleImplicitAnimation: View {
@State private var isTapped = false
var body: some View {
VStack(spacing: 30) {
// 圆形视图 - 点击后会放大并变色
Circle()
.fill(isTapped ? .blue : .red) // 颜色变化
.frame(width: isTapped ? 150 : 100, // 大小变化
height: isTapped ? 150 : 100)
.animation(.easeInOut(duration: 0.5), value: isTapped) // 隐式动画
Button("点击动画") {
isTapped.toggle() // 状态变化自动触发动画
}
}
}
}
1.2、显式动画
显式动画使用 withAnimation 闭包,只对闭包内的状态变化应用动画。可以精确控制哪些状态变化应该动画,以及使用什么样的动画参数。
显式动画特点:
- 使用 withAnimation { } 闭包
- 精确控制哪些变化有动画
- 手动触发动画
swift
struct SimpleExplicitAnimation: View {
@State private var isTapped = false
var body: some View {
VStack(spacing: 30) {
// 圆形视图
Circle()
.fill(isTapped ? .green : .orange) // 颜色变化
.frame(width: isTapped ? 150 : 100, // 大小变化
height: isTapped ? 150 : 100)
// 注意:这里没有 .animation() 修饰符
Button("点击动画") {
// 使用 withAnimation 显式包装状态变化
withAnimation(.easeInOut(duration: 0.5)) {
isTapped.toggle() // 只有这个变化有动画
}
}
}
}
}
1.3、动画曲线
在 SwiftUI 中,动画曲线(也称为时序曲线或缓动函数)定义了动画随时间变化的速度和节奏。它们让动画看起来更自然、更流畅。
1.3.1、线性动画 (Linear)
匀速动画,速度保持不变。
swift
.animation(.linear(duration: 1.0), value: value)
1.3.2、缓动动画 (Ease)
速度会变化,提供更自然的运动效果。
包含:缓入(.easeIn)、缓出(.easeOut)、缓入缓出(.easeInOut,默认)
swift
.animation(.easeInOut(duration: 1.0), value: value)
// 开始慢 → 中间快 → 结束慢
// 最自然的运动曲线
swift
.animation(.easeIn(duration: 1.0), value: value)
// 开始慢 → 逐渐加速到结束
swift
.animation(.easeOut(duration: 1.0), value: value)
// 开始快 → 逐渐减速到结束
1.3.3、弹性动画 (Spring)
模拟弹簧物理效果,带有回弹。
swift
.animation(
.spring(
response: 0.6, // 持续时间
dampingFraction: 0.8, // 阻尼(0-1,越小弹性越大)
blendDuration: 0.25 // 混合持续时间
),
value: value
)
1.3.4、交互式弹簧 (Interpolating Spring)
更精确控制弹簧物理参数的动画。
swift
.animation(
.interpolatingSpring(
mass: 1.0, // 质量:影响惯性
stiffness: 100, // 刚度:影响回弹力度
damping: 10, // 阻尼:影响阻力
initialVelocity: 0 // 初始速度
),
value: value
)
1.3.5、自定义动画曲线
timingCurve 是 SwiftUI 中用于创建自定义动画曲线的函数,它使用三次贝塞尔曲线来精确控制动画的加速和减速过程。
swift
.animation(
.timingCurve(
0.25, // 控制点1 X: 开始阶段的弯曲程度
0.1, // 控制点1 Y: 开始阶段的速度
0.25, // 控制点2 X: 结束阶段的弯曲程度
1.0, // 控制点2 Y: 结束阶段的速度
duration: 1.0 // 动画总时长
),
value: value
)
1.4、动画重复
1.4.1、使用 repeatCount 指定重复次数
swift
struct RepeatCountExample: View {
@State private var scale: CGFloat = 1.0
var body: some View {
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.scaleEffect(scale)
.onAppear {
withAnimation(
.easeInOut(duration: 0.5)
.repeatCount(3) // 重复3次
) {
scale = 1.5
}
}
}
}
1.4.2、使用 repeatForever 无限重复
swift
struct RepeatForeverExample: View {
@State private var rotation: Double = 0
var body: some View {
Rectangle()
.fill(Color.red)
.frame(width: 100, height: 100)
.rotationEffect(.degrees(rotation))
.onAppear {
withAnimation(
.linear(duration: 1.0)
.repeatForever(autoreverses: false) // 无限重复,不自动反向
) {
rotation = 360
}
}
}
}
1.4.3、带自动反向的重复
swift
struct AutoreverseExample: View {
@State private var offsetY: CGFloat = 0
var body: some View {
Circle()
.fill(Color.green)
.frame(width: 80, height: 80)
.offset(y: offsetY)
.onAppear {
withAnimation(
.easeInOut(duration: 0.8)
.repeatForever(autoreverses: true) // 来回弹跳
) {
offsetY = 100
}
}
}
}
2、基础动画示例
2.1、位移动画 (Move)
swift
import SwiftUI
struct MoveAnimationSimple: View {
@State private var moveRight = false
var body: some View {
VStack {
Circle()
.fill(.blue)
.frame(width: 80, height: 80)
.offset(x: moveRight ? 100 : 0) // X轴位移
.animation(.easeInOut(duration: 1.0), value: moveRight)
Button("移动") {
moveRight.toggle()
}
}
}
}
2.2、旋转动画 (Rotation)
swift
struct RotationAnimationSimple: View {
@State private var rotate = false
var body: some View {
VStack {
Rectangle()
.fill(.red)
.frame(width: 100, height: 100)
.rotationEffect(.degrees(rotate ? 180 : 0)) // 旋转角度
.animation(.easeInOut(duration: 1.0), value: rotate)
Button("旋转") {
rotate.toggle()
}
}
}
}
2.3、缩放动画 (Scale)
swift
struct ScaleAnimationSimple: View {
@State private var scaleUp = false
var body: some View {
VStack {
Circle()
.fill(.green)
.frame(width: 80, height: 80)
.scaleEffect(scaleUp ? 1.5 : 1.0) // 缩放比例
.animation(.easeInOut(duration: 1.0), value: scaleUp)
Button("缩放") {
scaleUp.toggle()
}
}
}
}
2.4、透明度动画 (Opacity)
swift
struct OpacityAnimationSimple: View {
@State private var show = false
var body: some View {
VStack {
Circle()
.fill(.orange)
.frame(width: 100, height: 100)
.opacity(show ? 1.0 : 0.3) // 透明度
.animation(.easeInOut(duration: 1.0), value: show)
Button("淡入/淡出") {
show.toggle()
}
}
}
}
2.5、颜色动画 (Color)
swift
struct ColorAnimationSimple: View {
@State private var changeColor = false
var body: some View {
VStack {
Rectangle()
.fill(changeColor ? .purple : .blue) // 颜色变化
.frame(width: 120, height: 120)
.animation(.easeInOut(duration: 1.0), value: changeColor)
Button("变色") {
changeColor.toggle()
}
}
}
}
2.6、圆角动画 (Corner Radius)
swift
struct CornerRadiusAnimationSimple: View {
@State private var roundCorners = false
var body: some View {
VStack {
Rectangle()
.fill(.red)
.frame(width: 120, height: 120)
.cornerRadius(roundCorners ? 60 : 0) // 圆角变化
.animation(.easeInOut(duration: 1.0), value: roundCorners)
Button("圆角") {
roundCorners.toggle()
}
}
}
}
3、组合动画示例
3.1、多个属性同时动画
同时为视图的多个属性应用动画
swift
struct CombinedAnimationView: View {
@State private var isAnimating = false
var body: some View {
VStack(spacing: 30) {
Text("组合动画")
.font(.title)
RoundedRectangle(cornerRadius: isAnimating ? 50 : 10)
.fill(isAnimating ? .blue : .red)
.frame(
width: isAnimating ? 200 : 100,
height: isAnimating ? 200 : 100
)
.rotationEffect(.degrees(isAnimating ? 180 : 0))
.opacity(isAnimating ? 0.8 : 1.0)
.animation(
.easeInOut(duration: 1.5),
value: isAnimating
)
Button("触发组合动画") {
isAnimating.toggle()
}
}
.padding()
}
}
3.2、序列动画
使用多个 withAnimation 创建顺序执行的动画
此处模拟实现按钮点击 - 果冻动画效果:

swift
struct Anim1: View {
@State private var scaleX = 1.0
@State private var scaleY = 1.0
var body: some View {
Button("button"){
doAnim()
}
.foregroundColor(.white)
.padding(.horizontal, 50)
.padding(.vertical, 40)
.background(Color.blue)
.cornerRadius(10)
.scaleEffect(x:scaleX, y: scaleY)
}
func doAnim(){
Task{@MainActor in
withAnimation(.spring(response:0.1, dampingFraction: 0.8)){
scaleX = 0.8
scaleY = 1.2
}
await try Task.sleep(for: .seconds(0.1))
withAnimation(.interpolatingSpring(mass: 1.0, stiffness: 200, damping: 8)){
scaleX = 1.0
scaleY = 1.0
}
}
}
}
4、Lottie动画
使用SwiftUI动画可实现基础的动画效果,如果动画包含复杂逻辑,建议使用Lottie实现(线上有很多的lottie动画文件(.json)可直接使用)
Lottie 是一个由 Airbnb 开发的开源库,用于在 iOS、Android 和 Web 上展示高质量的动画。使用 Lottie 动画能够为你的 SwiftUI 应用增添更丰富的交互和视觉效果,同时保持良好的性能和用户体验。
SwiftUI 中使用 Lottie 动画的一般步骤:
1、安装 Lottie 库:可以使用Swift Package Manager 或者 CocoaPods
2、SwiftUI 视图导入 Lottie 模块:import Lottie
3、Lottie 动画 JSON 文件添加到你的项目中
4、SwiftUI 视图中使用 LottieView加载动画文件

json文件管理、动画加载参考:

