I would like to have BarMark with cross-hatched pattern by using Charts in a SwiftUI project. My data type is (Date, Double).
I created a chart like this:
struct ContentView: View {
struct ChartData: Hashable {
let date: Date
let value: Double
}
@State private var model: [ChartData] = [
ChartData(date: Calendar.current.date(byAdding: .month, value: -1, to: Date())!, value: 70),
ChartData(date: Date(), value: 170),
ChartData(date: Calendar.current.date(byAdding: .month, value: 1, to: Date())!, value: 45)
]
private let barWidth: CGFloat = 40.0
var body: some View {
Chart {
ForEach(model, id: \.self) { data in
BarMark(
x: .value("Date", data.date),
yStart: .value("Start", 0),
yEnd: .value("End", data.value),
width: .fixed(barWidth)
)
.foregroundStyle(.yellow)
}
}
.chartXAxis(.hidden)
.chartYAxis(.hidden)
.padding()
}
}
This is the desired BarMark:
Thanks in advance
You can use an ImagePaint
as the foregroundStyle
of the bar marks.
You just need to have a pattern image like this:
You can create such an image by drawing like this:
let pattern = Image(size: .init(width: 40, height: 30)) { gc in
gc.fill(Path(CGRect(x: 0, y: 0, width: 40, height: 30)), with: .color(.orange.opacity(0.3)))
func stroke(from: CGPoint, to: CGPoint) {
gc.stroke(Path { p in
p.move(to: from)
p.addLine(to: to)
}, with: .color(.orange), style: .init(lineWidth: 10, lineCap: .square))
}
stroke(from: .init(x: 40, y: 0), to: .init(x: 0, y: 30))
stroke(from: .init(x: 40, y: -30), to: .zero)
stroke(from: .init(x: 40, y: 30), to: .init(x: 0, y: 60))
}
or create one in Photoshop or whatever software you have.
Then you can just do
.foregroundStyle(.image(pattern))