如何完全复制具有覆盖选项的Swift图表的默认样式

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

foregroundStyle(_:)
修饰符:
private let symbols = ["circle", "square", "triangle", "diamond", "pentagon"]
private let styles: [Color] = [ .blue, .green, .orange, .purple, .red, .cyan, .yellow ]
// Swift Charts just cycles through the above choices, resulting in 35 (7x5) unique combinations

private struct StandardChart: View {
    func chartPoint(x: Int, y: Double, series: Int) -> some ChartContent {
        LineMark(
            x: .value("Day", x),
            y: .value("Total", y),
            series: .value("Series", "Series \(series + 1)")
        )
        .symbol(by: .value("Series", "Series \(series + 1)"))
        .foregroundStyle(by: .value("Series", "Series \(series + 1)"))
    }

    var body: some View {
        Chart {
            ForEach(0..<8, id: \.self) { index in
                chartPoint(x: 0, y: 0, series: index)
                chartPoint(x: 1, y: 0.75 * Double(index), series: index)
                chartPoint(x: 2, y: Double(index), series: index)
            }
        }
    }
}

private struct ReproducedChart: View {
    func chartPoint(x: Int, y: Double, series: Int) -> some ChartContent {
        LineMark(
            x: .value("Day", x),
            y: .value("Total", y),
            series: .value("Series", "Series \(series + 1)")
        )
        .symbol {
            Image(systemName: symbols[series % 5])
                .font(.system(size: 7))
                .fontWeight(.black)
        }
        .foregroundStyle(styles[series % 7])
    }

    var body: some View {
        VStack {
            Chart {
                ForEach(0..<8, id: \.self) { index in
                    chartPoint(x: 0, y: 0, series: index)
                    chartPoint(x: 1, y: 0.75 * Double(index), series: index)
                    chartPoint(x: 2, y: Double(index), series: index)
                }
            }
        }
    }
}

// Best viewed in landscape mode
struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                Text("Standard")
                StandardChart()
            }
            .padding()

            VStack {
                Text("Reproduced")
                ReproducedChart()
            }
            .padding()
        }
    }
}
在:

我的代码即将接近,但看起来与默认值不完全相同。以下是我在图表的复制版本中注意到的差异:Side by side comparison of differing charts

符号的中风较薄。

情节线侵占了符号的内部。

符号没有捡起颜色。
图表没有出现传奇

    关于如何解决这些问题的任何想法?
  • well,我已经准备好发布上述问题,但是经过自己的调查,我找到了解决方案。因此,我正在回答这种问答风格,因此像我一样,其他人从错误的道路上开始的其他人可以从我的发现中受益。
  • 首先要注意的是,即使Swift图表允许您提供
  • ReproducedChart
指定SFSymbols代替默认点标记,并且似乎有SFSymbols似乎与默认点标记完全相对应,Swift图表实际上并未在引擎盖下使用SFSymbols进行默认样式。而是使用

Image(systemName:)
swiftui swiftui-charts
1个回答
0
投票
。目前(ios18.3)我们有以下选择:

BasicChartSymbolShape

asterisk

circle
cross
diamond
pentagon
plus
square
triangle
使用
BasicChartSymbolShape
,而不是SFSymbols将解决问题中的前三个问题。 ie用
private let symbols = ["circle", ...]
替换为
private let symbols: [BasicChartSymbolShape] = [.circle, ...]
,然后用
symbol {...}
替换为

ReproducedChart

缺少图表传奇的最后一期更加微妙。事实证明,即使我对我指定的系列始终如一地对所有内容进行了样式,但Swift图表也许并不合理地假设我将在“系列1”等的所有标记中使用正确的符号。 API不能保证我的正确选择。因此,传说中的任何信息都不能来自诸如
.symbol(symbols[series % 5])
symbol(_:)
之类的API,而我们必须使用
foregroundStyle(_:)

symbol(by:)

。这些API保证将在同一系列中的所有元素中应用一致的样式。
但是,似乎我们又回到了对造型选择的控制权!但是,我们可以重新控制使用图表API中的各种修饰符做出的选择,这些选择以formforegroundStyle(by:)
表命名。在这种情况下,最直接的一种似乎是
chart*Scale(...)
chartSymbolScale(_:)
,我发现形式的修饰符是,也就是说,所有以他们的论点为论点的修饰符都是非常脆弱的。如果我在视图中使用了多个这样的修饰符,我什至无法获得XCode来编译代码。
我建议的替代方法是使用将映射函数作为参数的修饰符之一。在此示例中,这意味着使用
Chart { // ... } .chartSymbolScale([ "Series 1": .circle, // ... "Series 8": .triangle ])

chart*Scale(_:)
提供为每个系列提供适当样式选择的映射功能。
在进行上述建议的更改之后,我们最终得到了此代码:

_ mapping: KeyValuePairs<DataValue, S>
以下结果:

现在我要做的就是更改映射函数返回的样式chartSymbolScale(mapping:)

chartForegroundStyleScale(mapping:),我将获得与默认值一致的结果!
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.