Article / 2026/05/29
SwiftUI Animation 完整 API 文档
🚀 SwiftUI Animation 完整 API 文档
目录
- Animation 基础概念
- Animation 类型
- Animation 修饰符
- Transaction API
- Transition API
- AnimatableModifier
- GeometryEffect
- 实践示例
1. Animation 基础概念
Animation 结构体
SwiftUI 中的 Animation 是一个描述动画如何随时间变化的结构体。
@frozen struct Animation: Equatable, Sendable
基本用法
// 方式1:使用 .animation() 修饰符
View.animation(_ animation: Animation?, value: some Equatable)
// 方式2:使用 withAnimation
withAnimation(_ animation: Animation?) {
// 状态改变
}
2. Animation 类型
2.1 预设动画
default
static let `default`: Animation
// 默认动画,等同于 easeInOut(duration: 0.35)
linear
static func linear(duration: TimeInterval = 0.35) -> Animation
// 线性动画,匀速运动
// duration: 动画持续时间(秒)
easeIn
static func easeIn(duration: TimeInterval = 0.35) -> Animation
// 缓入动画,开始慢后快
// duration: 动画持续时间(秒)
easeOut
static func easeOut(duration: TimeInterval = 0.35) -> Animation
// 缓出动画,开始快后慢
// duration: 动画持续时间(秒)
easeInOut
static func easeInOut(duration: TimeInterval = 0.35) -> Animation
// 缓入缓出动画,开始和结束慢,中间快
// duration: 动画持续时间(秒)
2.2 弹性动画
spring
static func spring(
response: Double = 0.5,
dampingFraction: Double = 0.825,
blendDuration: Double = 0
) -> Animation
// response: 弹簧的刚度,控制动画速度
// dampingFraction: 阻尼系数 (0-1),1 表示临界阻尼
// blendDuration: 动画混合持续时间
interactiveSpring
static func interactiveSpring(
response: Double = 0.15,
dampingFraction: Double = 0.86,
blendDuration: Double = 0.25
) -> Animation
// 适用于交互式动画的弹簧效果
interpolatingSpring
static func interpolatingSpring(
stiffness: Double,
damping: Double,
initialVelocity: Double = 0
) -> Animation
// stiffness: 弹簧刚度
// damping: 阻尼值
// initialVelocity: 初始速度
smooth
static func smooth(duration: TimeInterval = 0.35) -> Animation
// iOS 17+
// 平滑动画,Apple 推荐的新动画类型
snappy
static func snappy(duration: TimeInterval = 0.35) -> Animation
// iOS 17+
// 快速响应的动画
bouncy
static func bouncy(duration: TimeInterval = 0.35) -> Animation
// iOS 17+
// 弹跳效果动画
2.3 自定义时间曲线
timingCurve
static func timingCurve(
_ c0x: Double, _ c0y: Double,
_ c1x: Double, _ c1y: Double,
duration: TimeInterval = 0.35
) -> Animation
// 贝塞尔曲线控制点
// c0x, c0y: 第一个控制点
// c1x, c1y: 第二个控制点
2.4 动画修饰方法
delay
func delay(_ delay: TimeInterval) -> Animation
// 延迟执行动画
speed
func speed(_ speed: Double) -> Animation
// 调整动画速度,2.0 = 两倍速,0.5 = 半速
repeatCount
func repeatCount(_ repeatCount: Int, autoreverses: Bool = true) -> Animation
// repeatCount: 重复次数
// autoreverses: 是否自动反向
repeatForever
func repeatForever(autoreverses: Bool = true) -> Animation
// 无限重复
// autoreverses: 是否自动反向
3. Animation 修饰符
3.1 animation(_:value:)
func animation<V>(
_ animation: Animation?,
value: V
) -> some View where V : Equatable
// 当 value 改变时应用动画
// animation: nil 时禁用动画
3.2 animation(_:)(已废弃)
@available(iOS, deprecated: 15.0)
func animation(_ animation: Animation?) -> some View
// iOS 15 后不推荐使用
3.3 withAnimation
func withAnimation<Result>(
_ animation: Animation? = .default,
_ body: () throws -> Result
) rethrows -> Result
// 在闭包内的所有状态改变都会应用动画
3.4 Binding 的动画
extension Binding {
func animation(_ animation: Animation? = .default) -> Binding<Value>
}
// 示例
@State private var isOn = false
Toggle("Switch", isOn: $isOn.animation(.spring()))
4. Transaction API
Transaction 结构体
struct Transaction {
var animation: Animation?
var disablesAnimations: Bool
var isContinuous: Bool
}
使用 Transaction
// 方式1:withTransaction
withTransaction(Transaction(animation: .spring())) {
// 状态改变
}
// 方式2:transaction 修饰符
.transaction { transaction in
transaction.animation = .easeInOut(duration: 2)
}
5. Transition API
5.1 预设转场
opacity
static let opacity: AnyTransition
// 淡入淡出
scale
static func scale(scale: CGFloat = 0) -> AnyTransition
// 缩放效果
slide
static let slide: AnyTransition
// 滑动效果
move
static func move(edge: Edge) -> AnyTransition
// 从指定边缘移动
// edge: .top, .bottom, .leading, .trailing
push
static func push(from edge: Edge) -> AnyTransition
// iOS 16+
// 推入效果
offset
static func offset(_ offset: CGSize) -> AnyTransition
static func offset(x: CGFloat = 0, y: CGFloat = 0) -> AnyTransition
// 偏移效果
5.2 组合转场
combined
func combined(with other: AnyTransition) -> AnyTransition
// 组合两个转场效果
asymmetric
static func asymmetric(
insertion: AnyTransition,
removal: AnyTransition
) -> AnyTransition
// 不对称转场,插入和移除使用不同效果
5.3 自定义转场
extension AnyTransition {
static func custom<M: ViewModifier>(
active: M,
identity: M
) -> AnyTransition
}
// 示例
struct CustomTransition: ViewModifier {
let opacity: Double
func body(content: Content) -> some View {
content.opacity(opacity)
}
}
extension AnyTransition {
static var customFade: AnyTransition {
.modifier(
active: CustomTransition(opacity: 0),
identity: CustomTransition(opacity: 1)
)
}
}
5.4 使用转场
// 基本用法
View.transition(_ transition: AnyTransition)
// 示例
if showView {
Text("Hello")
.transition(.slide)
}
6. AnimatableModifier
协议定义
protocol AnimatableModifier: Animatable, ViewModifier {
var animatableData: AnimatableData { get set }
}
实现示例
struct AnimatedProgress: AnimatableModifier {
var progress: Double
var animatableData: Double {
get { progress }
set { progress = newValue }
}
func body(content: Content) -> some View {
content
.opacity(progress)
.scaleEffect(progress)
}
}
7. GeometryEffect
协议定义
protocol GeometryEffect: Animatable, ViewModifier {
func effectValue(size: CGSize) -> ProjectionTransform
}
实现示例
struct RotateEffect: GeometryEffect {
var angle: Double
var animatableData: Double {
get { angle }
set { angle = newValue }
}
func effectValue(size: CGSize) -> ProjectionTransform {
let rotation = CGAffineTransform(rotationAngle: angle * .pi / 180)
let offset = CGAffineTransform(translationX: size.width/2, y: size.height/2)
return ProjectionTransform(rotation.concatenating(offset))
}
}
8. 实践示例
8.1 基础动画
struct BasicAnimationView: View {
@State private var scale = 1.0
var body: some View {
Circle()
.scaleEffect(scale)
.animation(.easeInOut(duration: 1), value: scale)
.onTapGesture {
scale = scale == 1.0 ? 1.5 : 1.0
}
}
}
8.2 组合动画
struct CombinedAnimationView: View {
@State private var show = false
var body: some View {
VStack {
if show {
RoundedRectangle(cornerRadius: 20)
.fill(Color.blue)
.frame(width: 200, height: 200)
.transition(
.asymmetric(
insertion: .scale.combined(with: .opacity),
removal: .slide.combined(with: .opacity)
)
)
}
Button("Toggle") {
withAnimation(.spring(response: 0.5, dampingFraction: 0.7)) {
show.toggle()
}
}
}
}
}
8.3 手势动画
struct GestureAnimationView: View {
@State private var offset = CGSize.zero
@State private var isDragging = false
var body: some View {
Circle()
.fill(isDragging ? Color.red : Color.blue)
.frame(width: 100, height: 100)
.offset(offset)
.animation(.spring(), value: offset)
.animation(.easeInOut, value: isDragging)
.gesture(
DragGesture()
.onChanged { value in
offset = value.translation
isDragging = true
}
.onEnded { _ in
offset = .zero
isDragging = false
}
)
}
}
8.4 连续动画
struct ChainedAnimationView: View {
@State private var step = 0
var body: some View {
Circle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.offset(x: CGFloat(step * 50))
.animation(.easeInOut(duration: 0.5), value: step)
.onAppear {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
step = (step + 1) % 5
}
}
}
}
8.5 相位动画 (iOS 17+)
struct PhaseAnimationView: View {
@State private var phase = 0
var body: some View {
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.phaseAnimator([0, 1, 2]) { view, phase in
view
.scaleEffect(1 + Double(phase) * 0.2)
.opacity(1 - Double(phase) * 0.2)
} animation: { phase in
.easeInOut(duration: 0.5)
}
}
}
性能优化建议
- 使用 value 参数: 始终使用
.animation(_, value:)而不是废弃的.animation(_) - 避免过度动画: 不要在大型列表或复杂视图层次中使用过多动画
- 使用 Transaction: 对于复杂的动画序列,使用 Transaction 来精确控制
- 动画隔离: 将动画应用到最小的视图子集
- 预计算值: 对于复杂的动画路径,预先计算值以提高性能
常见问题解决
动画不生效
- 确保视图是可动画的(实现了 Animatable 协议)
- 检查是否有多个动画修饰符冲突
- 使用
.animation(nil)显式禁用不需要的动画
动画闪烁
- 避免在动画过程中改变视图标识
- 使用
.id()修饰符保持视图身份 - 检查是否有隐式动画干扰
性能问题
- 减少动画的复杂度
- 使用
drawingGroup()对复杂动画进行光栅化 - 避免在动画中进行大量计算
Giscus 未启用:请在
src/site.config.ts中配置 repoId 与 categoryId。