SwiftUI中图表与图例符号不一致问题求助
SwiftUI图表图例符号与图表内符号不一致的解决方法
问题说明
在SwiftUI中使用.symbol(by:)修饰符生成图例时,出现图例符号与图表中指定符号不匹配的问题:图表里明确用了triangle和plus符号,但图例自动生成了circle和square,忽略了自定义符号设置,需要让两者保持一致。
原问题代码
struct Line: Identifiable { let xyzipped: [(Double, Double)] let symbol: BasicChartSymbolShape let legendStr: String let id = UUID() init(x: [Double], y: [Double], symbol: BasicChartSymbolShape, legendStr: String) { self.xyzipped = Array(zip(x, y)) self.symbol = symbol self.legendStr = legendStr } } struct ChartOfLines: View { let lines: [Line] init() { let line1 = Line(x: [0, 1, 2, 3, 4], y: [3, 5, 8, -1, 0], symbol: BasicChartSymbolShape.triangle, legendStr: "line1") let line2 = Line(x: [0, 1, 2, 3, 4], y: [5, 4, 3, 7, 1], symbol: BasicChartSymbolShape.plus, legendStr: "line2") lines = [line1, line2] } var body: some View { Chart(lines, id: \.id) { line in ForEach(line.xyzipped, id:\.0) { xy in LineMark( x: .value("X values", xy.0), y: .value("Y values", xy.1) ) .lineStyle(StrokeStyle(lineWidth: 0.5)) PointMark( x: .value("X values", xy.0), y: .value("Y values", xy.1) ) } .symbol(line.symbol) .symbol(by: .value("", line.legendStr)) .foregroundStyle(by: .value("", line.legendStr)) } .frame(width: 500, height: 500) .padding() } }
解决思路与修正代码
问题核心是:.symbol(line.symbol)被.symbol(by:)覆盖了——.symbol(by:)会默认根据分类分配符号,忽略之前的自定义设置。要让自定义符号同步到图例,需要用.symbol(by:)的闭包版本,直接绑定分类与自定义符号的映射关系。
修正后的代码
struct ChartOfLines: View { let lines: [Line] init() { let line1 = Line(x: [0, 1, 2, 3, 4], y: [3, 5, 8, -1, 0], symbol: BasicChartSymbolShape.triangle, legendStr: "line1") let line2 = Line(x: [0, 1, 2, 3, 4], y: [5, 4, 3, 7, 1], symbol: BasicChartSymbolShape.plus, legendStr: "line2") lines = [line1, line2] } var body: some View { Chart(lines, id: \.id) { line in ForEach(line.xyzipped, id:\.0) { xy in // 折线样式绑定图例颜色 LineMark( x: .value("X values", xy.0), y: .value("Y values", xy.1) ) .lineStyle(StrokeStyle(lineWidth: 0.5)) .foregroundStyle(by: .value("图例", line.legendStr)) // 点标记绑定自定义符号与图例 PointMark( x: .value("X values", xy.0), y: .value("Y values", xy.1) ) .symbol(by: .value("图例", line.legendStr)) { _ in line.symbol } .foregroundStyle(by: .value("图例", line.legendStr)) } } .frame(width: 500, height: 500) .padding() } }
关键说明
- 使用
.symbol(by:_:)的闭包版本,直接根据分类返回模型中定义的自定义符号,确保图表点和图例使用同一符号。 - 保持
foregroundStyle(by:)和symbol(by:)使用相同的分类键(如示例中的"图例"),保证图例与图表元素的关联一致性。 - 原代码中
.symbol(line.symbol)在.symbol(by:)之后执行,会被默认符号覆盖,因此必须通过分类绑定的方式设置自定义符号。
内容的提问来源于stack exchange,提问作者Ismet Sahin
相关产品推荐
相关产品推荐

