You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中能否访问withAnimation运行时的动画属性并用于修改其他视图属性?

SwiftUI中能否访问withAnimation运行时的动画属性并用于修改其他视图属性?

当然可以实现!不过默认的withAnimation隐式动画没办法直接获取动画的实时进度、速度这类中间状态——我们得换用显式追踪动画状态的方式,利用SwiftUI的Animatable协议来实现需求。下面就给你一步步拆解如何让文本的模糊程度随动画速度变化:

核心思路

我们需要自定义一个可动画修饰符,让它在动画运行的每一帧里,实时计算当前的动画速度,再把这个速度值绑定到文本的模糊效果上。具体分为两步:

  1. 用一个ObservableObject来保存和传递实时的动画速度
  2. 自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 13:34:35