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

SwiftUI中如何实现RoundedRectangle的Trim永久旋转动画?

解决方案:实现圆角矩形Trim片段的流畅循环游动动画

要实现你想要的两条蛇依次沿圆角矩形边缘移动的效果,核心是通过动态调整trim的from和to参数,配合持续的线性动画进度来驱动,而非依赖布尔值切换和旋转缩放。以下是修改后的代码:

import SwiftUI

struct SnakeTrimAnimationView: View {
    // 示例渐变颜色
    private let colors: [Color] = [.blue, .purple, .pink]
    // 动画进度值,从0到1循环递增
    @State private var progress = 0.0
    
    // 单个蛇形片段占总路径的比例
    private let segmentLength = 0.25
    // 两个片段的偏移差,实现依次移动的错开效果
    private let segmentOffset = 0.5
    
    var body: some View {
        ZStack {
            // 背景灰色圆角矩形
            RoundedRectangle(cornerRadius: 20, style: .continuous)
                .foregroundColor(.gray.opacity(0.1))
                .frame(width: 195, height: 50)
            
            // 第一条蛇形片段
            RoundedRectangle(cornerRadius: 20, style: .continuous)
                .trim(
                    from: progress.truncatingRemainder(dividingBy: 1),
                    to: (progress + segmentLength).truncatingRemainder(dividingBy: 1)
                )
                .stroke(
                    LinearGradient(gradient: Gradient(colors: colors), startPoint: .topLeading, endPoint: .bottomTrailing),
                    style: StrokeStyle(lineWidth: 3, lineCap: .round)
                )
                .frame(width: 195, height: 50)
            
            // 第二条蛇形片段(偏移半程,实现依次移动)
            RoundedRectangle(cornerRadius: 20, style: .continuous)
                .trim(
                    from: (progress + segmentOffset).truncatingRemainder(dividingBy: 1),
                    to: (progress + segmentOffset + segmentLength).truncatingRemainder(dividingBy: 1)
                )
                .stroke(
                    LinearGradient(gradient: Gradient(colors: colors), startPoint: .topLeading, endPoint: .bottomTrailing),
                    style: StrokeStyle(lineWidth: 3, lineCap: .round)
                )
                .frame(width: 195, height: 50)
            
            // 标题文本
            Text("title")
                .foregroundStyle(LinearGradient(gradient: Gradient(colors: colors), startPoint: .topLeading, endPoint: .bottomTrailing))
        }
        .onAppear {
            // 启动永久循环的线性动画
            withAnimation(.linear(duration: 4).repeatForever(autoreverses: false)) {
                progress = 1.0
            }
        }
    }
}

#Preview {
    SnakeTrimAnimationView()
}

关键修改说明:

  • 用progress进度值替代布尔值:通过从0到1的持续递增进度,精准控制trim的起始和结束位置,实现平滑的路径移动。
  • 循环路径计算:利用truncatingRemainder(dividingBy: 1)让进度值超过1后自动归零,形成无限循环的动画。
  • 片段偏移设置:第二条片段的进度加上segmentOffset(0.5),让两个片段始终保持半程距离,实现"依次移动"的蛇形效果。
  • 统一帧尺寸:去掉原代码中动态缩放的逻辑,让trim片段始终贴合背景矩形的边缘,避免变形。
  • 渐变描边:将渐变直接应用到stroke上,让蛇形片段的颜色和标题保持一致。

你可以调整duration(动画时长)和segmentLength(片段长度)来控制动画的速度和片段大小,适配你想要的视觉效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:40:35