SwiftUI中能否访问withAnimation运行时的动画属性并用于修改其他视图属性?
SwiftUI中能否访问withAnimation运行时的动画属性并用于修改其他视图属性?
当然可以实现!不过默认的withAnimation隐式动画没办法直接获取动画的实时进度、速度这类中间状态——我们得换用显式追踪动画状态的方式,利用SwiftUI的Animatable协议来实现需求。下面就给你一步步拆解如何让文本的模糊程度随动画速度变化:
核心思路
我们需要自定义一个可动画修饰符,让它在动画运行的每一帧里,实时计算当前的动画速度,再把这个速度值绑定到文本的模糊效果上。具体分为两步:
- 用一个
ObservableObject来保存和传递实时的动画速度 - 自定义
AnimatableModifier,追踪动画的offset变化,计算速度并更新到追踪器中
完整实现代码
import SwiftUI // 用来保存和传递动画速度的追踪器 class AnimationSpeedTracker: ObservableObject { @Published var currentSpeed: CGFloat = 0 private var lastOffsetValue: CGFloat = 0 private var lastUpdateTime: Date = Date() } // 自定义可动画修饰符,负责追踪offset动画并计算速度 struct AnimationTrackingModifier: AnimatableModifier { var currentOffset: CGFloat @ObservedObject var speedTracker: AnimationSpeedTracker // 动画驱动的核心数据——这里就是我们要动画的offset var animatableData: CGFloat { get { currentOffset } set { let now = Date() let timeDiff = now.timeIntervalSince(speedTracker.lastUpdateTime) // 计算速度:偏移量变化值 / 时间间隔,缩放系数让模糊效果更直观 if timeDiff > 0 { speedTracker.currentSpeed = abs(newValue - speedTracker.lastOffsetValue) / CGFloat(timeDiff) * 0.01 } // 更新上一帧的记录值 speedTracker.lastOffsetValue = newValue speedTracker.lastUpdateTime = now currentOffset = newValue } } func body(content: Content) -> some View { content.offset(y: currentOffset) } } // 给View加个扩展,方便快速调用自定义修饰符 extension View { func trackingOffset(_ offset: CGFloat, with tracker: AnimationSpeedTracker) -> some View { self.modifier(AnimationTrackingModifier(currentOffset: offset, speedTracker: tracker)) } } // 主视图 struct ContentView: View { @State private var targetOffset: CGFloat = 0 @StateObject private var speedTracker = AnimationSpeedTracker() var body: some View { NavigationView { VStack { Text("Some moving text") .trackingOffset(targetOffset, with: speedTracker) .blur(radius: speedTracker.currentSpeed) // 用实时速度控制模糊半径 Button("Change Offset") { withAnimation(.easeInOut(duration: 1.0)) { targetOffset = .random(in: -400...400) } } } } } }
代码说明
- 当你点击按钮触发动画时,
withAnimation会驱动targetOffset的变化,而自定义修饰符会在每一帧更新时计算当前的动画速度 - 速度值通过
AnimationSpeedTracker传递给文本的blur修饰符,速度越快,模糊半径越大,完全符合你的需求 - 你可以调整速度计算里的缩放系数(
* 0.01),来控制模糊效果的强弱程度
这种方法是纯SwiftUI原生实现,不需要依赖UIKit,而且能精准追踪动画的实时状态~
备注:内容来源于stack exchange,提问作者Andrei Herford
相关产品推荐
相关产品推荐

