I want to use symbols in a bar chart to represent a habit the user specifies. Text can be too long and gets cut off by the next chart.
Here is what I tried:
Chart {
ForEach(habitItems) { habit in
BarMark(x: .value("Type", Image(systemName: habit.symbolHI)),
y: .value("Tracked", countTrackedDates(for: habit))
)
.foregroundStyle(getBarColor(for: habit).gradient)
.cornerRadius(20)
}
}
habit.symbolHI would equal a string for example: "square.fill"
I am getting an error:
Initializer 'init(x:y:width:height:stacking:)' requires that 'Image' conform to 'Plottable'
Maybe there is a way to make an image plottable but I'm not sure how.
CodePudding user response:
For simplicity, I'll assume you have an array of these:
struct Habit: Identifiable {
let symbolName: String
let count: Int
let color: Color
var id: String { symbolName }
}
You can just plot the name of the image.
BarMark(x: .value("Type", habit.symbolName),
y: .value("Tracked", habit.count)
)
Then use chartXAxis to change the X axis marks to images:
Chart {
...
}
.chartXAxis {
AxisMarks { value in
AxisValueLabel {
Image(systemName: value.as(String.self)!)
.font(.system(size: 30))
}
}
}
I am casting value to String here because I know I'm plotting strings on the x axis (as in x: .value("Type", habit.symbolName)). You can also use habitItems[value.index].symbolName if the indices of the x axis marks match the indices of your data (this would work if the data is an Array, but would not be the case if it is an ArraySlice in the middle of an array for example).
