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

SwiftUI中使用Trim实现带分段间隔与圆角的环形饼图

SwiftUI环形饼图实现问题

我需要实现设计师要求的环形饼图,目前已经能画出基础的环形分段,但卡在了分段间的间隔和圆角效果上——尝试添加边框无效,微调Trim参数来做间隔的话视觉效果很差。想请教下这个设计能不能在SwiftUI里实现,还是得让设计师调整方案?

我的现有实现代码:

import SwiftUI

struct ContentView: View {
    @ObservedObject var charDataObj = ChartDataContainer()
    @State var indexOfTappedSlice = -1
    
    var body: some View {
        VStack {
            Spacer()
            
            ZStack {
                Circle()
                    .stroke(Color(hex: 0x2A3950), style: StrokeStyle(lineWidth: 100, lineCap: .round, lineJoin: .round))
                    .frame(width: 220, height: 270)
                
                ForEach(0..<charDataObj.chartData.count) { index in
                    Circle()
                        .trim(from: index == 0 ? 0.0 : charDataObj.chartData[index-1].value / 100,
                              to: (charDataObj.chartData[index].value / 100))
                        .stroke(charDataObj.chartData[index].color, style: StrokeStyle(lineWidth: 50.0, lineCap: .butt, lineJoin: .round))
                        .rotationEffect(Angle(degrees: 270.0))
                        .onTapGesture {
                            indexOfTappedSlice = indexOfTappedSlice == index ? -1 : index
                        }
                        .scaleEffect(index == indexOfTappedSlice ? 1.1 : 1.0)
                        .animation(.spring())
                }
            }.frame(width: 150, height: 150)
            
            Spacer()
        }
        .frame(maxWidth: .infinity)
        .background(Color(hex: 0x42506B))
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

//MARK:- Chart Data
struct ChartData {
    var id = UUID()
    var color : Color
    var percent : CGFloat
    var value : CGFloat
}

@available(iOS 15.0, *)
class ChartDataContainer : ObservableObject {
    @Published var chartData =
    [ChartData(color: .green, percent: 26, value: 0),
     ChartData(color: .blue, percent: 28, value: 0),
     ChartData(color: .white, percent: 23, value: 0),
     ChartData(color: .yellow, percent: 12, value: 0),
     ChartData(color: .red, percent: 11, value: 0),]
    
    init() {
        calc()
    }
    func calc(){
        var value : CGFloat = 0
        
        for i in 0..<chartData.count {
            value += chartData[i].percent
            chartData[i].value = value
        }
    }
}

extension Color {
    init(hex: Int, opacity: Double = 1.0) {
        let red = Double((hex & 0xff0000) >> 16) / 255.0
        let green = Double((hex & 0xff00) >> 8) / 255.0
        let blue = Double((hex & 0xff) >> 0) / 255.0
        self.init(.sRGB, red: red, green: green, blue: blue, opacity: opacity)
    }
}

我尝试过微调Trim参数来制造间隔,但效果很差,代码如下:

.trim(from: index == 0 ? 0.003: (charDataObj.chartData[index-1].value / 100) + 0.003,
      to: (charDataObj.chartData[index].value / 100) - 0.003)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:45:39