使用 SwiftUI SectorMark 的半圆环图

问题描述 投票:0回答:2

我正在尝试使用新的 SectorMark 创建一个半圆环图,如图像所示:

到目前为止,我刚刚使用示例数据创建了一个普通的甜甜圈来填充它:

struct Score: Identifiable {
    let id = UUID()
    let type: String
    let value: Int
}

@State private var scores: [Score] = [
    .init(type: "Hits", value: 1),
    .init(type: "Misses", value: 9)
]

Chart(scores) { score in
    SectorMark(
         angle: .value("Values", score.value),
          innerRadius: .ratio(0.9),
          outerRadius: .ratio(0.7)
    )
    .foregroundStyle(
         by: .value("Type", score.type)
     )
}

在我试图创建的图表中,我仅使用部分来显示一个人的分数(他/她回答正确和错误的答案数量)。

使用 SectorMark 是否有可能实现这一目标?我从这个苹果视频中发现了这个新功能:https://developer.apple.com/videos/play/wwdc2023/10037/

swiftui charts donut-chart swiftui-charts
2个回答
1
投票

所以我决定使用@Sweeper建议的方法,它对我有用。由于我的图表仅使用两个值,因此我使用了带有两个圆形形状的 ZStack,如下所示:

ZStack {
   Circle()
     .trim(from: 0.0, to: 0.7)
     .stroke(Color.defaultBlue, style: StrokeStyle(lineWidth: 8, lineCap: .round))
     .frame(width: screenSize.width * 0.4, height: screenSize.height * 0.2)
     .rotationEffect(.degrees(-215))
                        
   Circle()
      .trim(from: 0.0, to: CGFloat(-- here you can use a percentage of your choice --) / (100 / 0.7))
      .stroke(Color.blue, style: StrokeStyle(lineWidth: 8, lineCap: .round))
      .frame(width: screenSize.width * 0.4, height: screenSize.height * 0.2)
      .rotationEffect(.degrees(-215))
}

这就是我的结果,正是我想要的:

(我从代码中删除了文本视图)

但是,如果您想知道是否有一种使用 SectorMark 的方法(这是本文最初的问题),是的,有,但不太优雅。

想象一下,如果您有像我这样的样本,即为图表使用两个值,您需要:

  1. 添加第三个,制作甜甜圈的另一半
  2. 将其涂成白色(或背景颜色)
  3. 旋转90度

这是代码:

struct Score: Identifiable {
    let id = UUID()
    let type: String
    let value: Int
    let color: Color
}

struct ContentView: View {
    
    @State private var scores: [Score] = [
        .init(type: "Hits", value: 1, color: .blue),
        .init(type: "Misses", value: 9, color: .green),
        .init(type: "", value: 10, color: .white)
    ]
    
    var body: some View {
        
        Chart(scores) { score in
            SectorMark(
                angle: .value("Values", score.value),
                innerRadius: .ratio(0.9),
                outerRadius: .ratio(0.7)
            )
            .foregroundStyle(score.color)
            .foregroundStyle(
                by: .value("Type", score.type)
            )
        }
        .rotationEffect(.degrees(-90))
    }
}

这就是结果:

您可能需要使用文本视图通过 VStack 添加图例。感谢 @Claude31 在 Apple 论坛上为我提供了帮助 (https://developer.apple.com/forums/thread/748142)

SectorMark 有很大的潜力,也许苹果可以在下次更新中实施半甜甜圈方法。


0
投票

圆形仪表是另一个可能满足您需求的 SwiftUI 选项。仪表只需要当前、最小值和最大值。

struct GaugeView: View {

@State private var current  = 3.0

let min = 0.0
let max = 10.0
let gradient = Gradient(colors: [.blue, .black])

var body: some View {
        Gauge(value: current, in: min...max) {
        } currentValueLabel: {
            Text("\(Int(current))")
                .foregroundColor(.blue)
        } minimumValueLabel: {
            Text("\(Int(min))")
        } maximumValueLabel: {
            Text("\(Int(max))")
        }
        .gaugeStyle(.accessoryCircular)
        .tint(gradient)
    }
}

看起来像这样:

© www.soinside.com 2019 - 2024. All rights reserved.