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

如何为SwiftUI圆弧添加阴影并优化全角显示效果?

嘿,我来帮你搞定这两个问题!咱们一步步来解决:

1. 解决全圆/超圆时的径向线问题

你的核心问题是当endAngle达到360度及以上时,圆弧两端重合导致渐变变成径向线。Apple Watch的解决方案是让圆弧即使满圈后也继续“多走一点点”,避免起点和终点完全重叠。我们可以用SwiftUI的trim修饰符来实现连续的多圈绘制,比直接用addArc更灵活。

替换你原来的Arc结构为下面的ProgressArc:

struct ProgressArc: Shape {
    @Binding var endAngle: Double
    let startAngle: Double = 270 // 固定起始角度为270度(顶部)
    var lineWidth: CGFloat = 50
    
    private var progress: Double {
        let totalAngle = endAngle - startAngle
        guard totalAngle >= 0 else { return 0 }
        // 计算进度:1.0代表一圈,超过1就是多圈
        return totalAngle / 360
    }
    
    func path(in rect: CGRect) -> Path {
        // 调整画布,避免圆弧超出边界(因为线宽的一半会在画布外)
        let adjustedRect = rect.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
        
        // 关键处理:当进度≥1(满圈)时,稍微增加一点进度,避免起点终点完全重合
        let adjustedProgress: CGFloat
        if progress >= 1 {
            // 增加0.001圈(约0.36度),既看不出缺口,又能避免径向线
            adjustedProgress = CGFloat(progress + 0.001)
        } else {
            adjustedProgress = CGFloat(progress)
        }
        
        return Circle()
            .trim(from: 0, to: adjustedProgress)
            .rotation(.degrees(startAngle)) // 旋转到起始角度(顶部)
            .path(in: adjustedRect)
    }
}

这个结构的优势:

  • 支持绘制任意圈数的圆弧(比如endAngle=720就是两圈)
  • 满圈时自动偏移一点点,彻底解决渐变径向线的问题
  • 保留了你原来的endAngle绑定,用法和之前一致
2. 添加Apple Watch风格的阴影

Apple Watch的活动环阴影是“凸起”的3D效果,我们可以用两层阴影+背景灰环来模拟:

struct ArcDemoView: View {
    @State private var endAngle = 450.0 // 测试1.25圈的效果
    
    var body: some View {
        ZStack {
            // 底层灰色背景环,模拟Apple Watch的默认环
            Circle()
                .stroke(Color.gray.opacity(0.3), lineWidth: 50)
                .padding(25) // 和进度环的线宽匹配,保证对齐
            
            // 进度环
            ProgressArc(endAngle: $endAngle, lineWidth: 50)
                .stroke(
                    AngularGradient(
                        gradient: Gradient(colors: [.red, .yellow, .green]),
                        center: .center,
                        startAngle: .degrees(270),
                        endAngle: .degrees(270 + 360)
                    ),
                    style: StrokeStyle(lineWidth: 50, lineCap: .round)
                )
                .padding(25)
                // 双层阴影模拟凸起效果
                .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: 3) // 底部阴影
                .shadow(color: .white.opacity(0.7), radius: 5, x: 0, y: -3) // 顶部高光阴影
        }
        .frame(width: 300, height: 300)
    }
}

阴影的细节说明:

  • 下层黑色阴影向下偏移,模拟凹陷的阴影
  • 上层白色高光阴影向上偏移,模拟凸起的反光
  • 背景灰环让进度环看起来更有层次感,和Apple Watch的设计一致
测试效果

你可以调整endAngle的值来测试不同场景:

  • endAngle=270:没有进度
  • endAngle=360:接近一圈(自动偏移了0.36度,无径向线)
  • endAngle=630:刚好一圈(同样无径向线)
  • endAngle=900:一圈半的连续圆弧

这样既解决了全圆时的径向线问题,又实现了和Apple Watch一致的阴影效果!

内容的提问来源于stack exchange,提问作者meaning-matters

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:42:13