Legend symbols produced by the .symbol(by:) modifier are different than the ones used in the chart. I specifically used the triangle and plus symbols in the chart, but they are disregarded and the circle and square symbols are produced automatically in the legend part. How can I make them agree?
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()
}
}
Create a custom chartLegend
if you want the ChartSymbolShape
to appear to the left of the legend string:
Example to test, adjust UI as necessary:
struct Line: Identifiable {
let xyzipped: [(Double, Double)]
let symbol: BasicChartSymbolShape
let legendStr: String
let lineColor: Color
let id = UUID()
init(x: [Double],
y: [Double],
symbol: BasicChartSymbolShape,
legendStr: String,
lineColor: Color)
{
self.xyzipped = Array(zip(x, y))
self.symbol = symbol
self.legendStr = legendStr
self.lineColor = lineColor
}
}
struct ContentView: 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", lineColor: .green)
let line2 = Line(x: [0, 1, 2, 3, 4],
y: [5, 4, 3, 7, 1],
symbol: BasicChartSymbolShape.plus,
legendStr: "line2", lineColor: .blue)
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(line.lineColor)
PointMark(
x: .value("X values", xy.0),
y: .value("Y values", xy.1)
)
.foregroundStyle(line.lineColor)
}
.symbol(line.symbol)
.foregroundStyle(by: .value("", line.legendStr))
}
.chartLegend(position: .bottomLeading, alignment: .bottomLeading) {
HStack() {
ForEach(lines) { xy in
HStack {
xy.symbol
.frame(width: 10, height: 10)
.foregroundColor(xy.lineColor)
Text(xy.legendStr).foregroundColor(.black)
}
}
}
}
.frame(width: 500, height: 500)
.padding()
}
}