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

SwiftUI实现Material Design风格波纹动画技术求助

SwiftUI Material Design 波纹效果完整实现

以下是修复并完善后的波纹效果实现,已经包含了从触摸点扩散至整个视图的缩放动画,完全贴合Material Design的交互规范:

import SwiftUI

struct Ripple: ViewModifier {
    let rippleColor: Color
    
    func body(content: Content) -> some View {
        GeometryReader { geo in
            ZStack {
                content
                
                if let touchPoint = touchPoint {
                    Circle()
                        .fill(rippleColor)
                        .position(touchPoint)
                        .scaleEffect(scale)
                        .opacity(opacity)
                        .animation(.easeOut(duration: 0.6), value: scale)
                }
            }
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged { gesture in
                        guard touchPoint != gesture.startLocation else { return }
                        
                        // 重置动画状态
                        scale = 0.01
                        opacity = 1.0
                        touchPoint = gesture.startLocation
                        
                        // 启动扩散动画
                        withAnimation(.easeOut(duration: 0.6)) {
                            // 计算覆盖整个视图所需的最小缩放比例
                            let maxDistance = max(
                                distance(from: touchPoint!, to: geo.frame(in: .local).topLeading),
                                distance(from: touchPoint!, to: geo.frame(in: .local).topTrailing),
                                distance(from: touchPoint!, to: geo.frame(in: .local).bottomLeading),
                                distance(from: touchPoint!, to: geo.frame(in: .local).bottomTrailing)
                            )
                            scale = maxDistance * 2 / 16 // 16是初始圆直径
                            opacity = 0.0
                        }
                    }
            )
        }
    }
    
    // MARK: 私有状态与方法
    @State private var scale: CGFloat = 0.01
    @State private var opacity: CGFloat = 0.0
    @State private var touchPoint: CGPoint?
    
    private func distance(from point1: CGPoint, to point2: CGPoint) -> CGFloat {
        sqrt(pow(point2.x - point1.x, 2) + pow(point2.y - point1.y, 2))
    }
}

extension View {
    func rippleEffect(rippleColor: Color = .accentColor.opacity(0.5)) -> some View {
        modifier(Ripple(rippleColor: rippleColor))
    }
}

// 使用示例
struct RippleDemo: View {
    var body: some View {
        Button("点击测试波纹") { }
            .padding()
            .background(.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
            .rippleEffect()
    }
}

关键修改说明

  • 几何尺寸计算:通过GeometryReader获取视图边界,计算触摸点到视图四个角落的最大距离,确保波纹能完全覆盖整个视图。
  • 同步动画:将缩放(scaleEffect)和透明度(opacity)的动画绑定,用withAnimation触发连贯的扩散消失效果,替代原代码中的Timer,更符合SwiftUI原生动画逻辑。
  • 手势优化:每次触摸时重置动画状态,确保重复点击能正确触发新波纹。
  • 初始状态调整:将波纹初始缩放设为极小值,避免初始显示的突兀感。

内容的提问来源于stack exchange,提问作者RPK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:20:23