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).