如何创建 .chartForegroundStyleScale 的动态输入

Fle*_*hil 8 swiftui swiftui-charts

chartForegroundStyleScale在 Swift Charts 中,为每个数据系列设置 ShapeStyle 的签名是:

func chartForegroundStyleScale<DataValue, S>(_ mapping: KeyValuePairs<DataValue, S>) -> some View where DataValue : Plottable, S : ShapeStyle
Run Code Online (Sandbox Code Playgroud)

初始化程序KeyValuePairs( init(dictionaryLiteral: (Key, Value)...)) 仅采用可变参数,因此任何从数组初始化前景样式的尝试(在我的例子中<String, Color>)都会导致错误:

Cannot pass array of type '[(String, Color)]' as variadic arguments of type '(String, Color)'
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,图表系列的名称是根据数据动态设置的,因此尽管我可以生成[String : Color]字典或元组数组,(String, Color)但我看不到可以将其中任何一个传递到chartForegroundStyleScale? 除非我遗漏了一些东西,否则这似乎是 Swift 图表中的一个奇怪的限制,即系列名称需要为此修饰符进行硬编码?

car*_*loe 8

您还可以将颜色数组传递给.chartForegroundStyleScale(range:). 只要您按照添加图形标记的顺序将颜色添加到数组中,它就应该可以正常工作。

也不是非常优雅,但这种方法适用于任意数量或条目。


struct GraphItem: Identifiable {
    var id = UUID()
    var label: String
    var value: Double
    var color: Color
}

struct ContentView: View {
    
    let data = [
        GraphItem(label: "Apples", value: 2, color: .red),
        GraphItem(label: "Pears", value: 3, color: .yellow),
        GraphItem(label: "Melons", value: 5, color: .green)
    ]
    
    var body: some View {
        Chart {
            ForEach(data, id: \.label) { item in
                BarMark(
                    x: .value("Count", item.value),
                    y: .value("Fruit", item.label)
                )
                .foregroundStyle(by: .value("Fruit", item.label))
            }
        }
        .chartForegroundStyleScale(range: graphColors(for: data))
    }
    
    func graphColors(for input: [GraphItem]) -> [Color] {
        var returnColors = [Color]()
        for item in input {
            returnColors.append(item.color)
        }
        return returnColors
    }
}

Run Code Online (Sandbox Code Playgroud)

  • 哎呀!!由于文档中的所有示例都使用“KeyValuePairs 初始值设定项”作为“chartForegroundStyleScale”,我完全错过了还有其他几个具有更灵活选项的初始值设定项,包括 ```func ChartForegroundStyleScale&lt;DataValue, S&gt;(mapping: @escaping (DataValue) -&gt; S) -&gt; 一些视图,其中 DataValue : Plottable, S : ShapeStyle``` 。这正是我所需要的 - 一个可以动态生成值的函数 (2认同)

Fle*_*hil 3

好的,我找到了一种方法,只要对条目数量的任意限制是可接受的(下面的示例,最大大小为 4:

func keyValuePairs<S, T>(_ from: [(S, T)]) -> KeyValuePairs<S, T> {
    switch from.count {
    case 1: return [ from[0].0 : from[0].1 ]
    case 2: return [ from[0].0 : from[0].1, from[1].0 : from[1].1 ]
    case 3: return [ from[0].0 : from[0].1, from[1].0 : from[1].1, from[2].0 : from[2].1 ]
    default: return [ from[0].0 : from[0].1, from[1].0 : from[1].1, from[2].0 : from[2].1, from[3].0 : from[3].1 ]
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我知道映射不会超过 20 个,因此可以扩展此函数以适应该数量。不理想,但它有效......