Right here is an instance exhibiting two completely different knowledge units on the identical axis. You want to scale the info your self although, so on this instance I’ve carried out so manually with the changes to the strain values, however you can additionally do that programatically.
Instance right here at github.com/jknlsn/MultipleDataSetSwiftChartsExample with lollipop element popover, and barely simplified instance under.
import Charts
import SwiftUI
import WeatherKit
struct HourWeatherStruct {
var date: Date
var strain: Double
var temperature: Double
var windSpeed: Double
}
let hours: [HourWeatherStruct] = [
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600),
pressure: 1015.0,
temperature: 18.2,
windSpeed: 6.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 2),
pressure: 1015.3,
temperature: 18.2,
windSpeed: 8.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 3),
pressure: 1015.9,
temperature: 18.2,
windSpeed: 9.4),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 4),
pressure: 1016.3,
temperature: 18.2,
windSpeed: 5.2),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 5),
pressure: 1016.3,
temperature: 18.2,
windSpeed: 12.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 6),
pressure: 1016.3,
temperature: 18.2,
windSpeed: 11.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 7),
pressure: 1017.3,
temperature: 18.2,
windSpeed: 10.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 8),
pressure: 1018.3,
temperature: 18.2,
windSpeed: 11.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 9),
pressure: 1018.3,
temperature: 18.2,
windSpeed: 9.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 10),
pressure: 1018.3,
temperature: 18.2,
windSpeed: 8.1),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 11),
pressure: 1017.3,
temperature: 18.2,
windSpeed: 19.9),
HourWeatherStruct(date: Date(timeIntervalSinceNow: 3600 * 12),
pressure: 1018.3,
temperature: 18.2,
windSpeed: 7.1),
]
struct InteractiveLollipopChartMinimal: View {
var physique: some View {
Chart {
ForEach(hours, id: .date) {
LineMark(
x: .worth("Date", $0.date, unit: .hour),
y: .worth("Wind Pace", $0.windSpeed)
)
.foregroundStyle(by: .worth("Worth", "Wind"))
LineMark(
x: .worth("Date", $0.date, unit: .hour),
y: .worth("Stress", ($0.strain - 1014) * 4)
)
.foregroundStyle(by: .worth("Worth", "Stress"))
}
.lineStyle(StrokeStyle(lineWidth: 4.0))
.interpolationMethod(.catmullRom)
}
.chartForegroundStyleScale([
"Pressure": .purple,
"Wind": .teal
])
.chartXAxis {
AxisMarks(place: .backside, values: .stride(by: .hour, depend: 2)) {
_ in
AxisTick()
AxisGridLine()
AxisValueLabel(format: .dateTime.hour(), centered: true)
}
}
.chartYAxis {
AxisMarks(place: .main, values: Array(stride(from: 0, by: 24, by: 4))){
axis in
AxisTick()
AxisGridLine()
AxisValueLabel("(1014 + (axis.index * 1))", centered: false)
}
AxisMarks(place: .trailing, values: Array(stride(from: 0, by: 24, by: 4))){
axis in
AxisTick()
AxisGridLine()
AxisValueLabel("(axis.index * 4)", centered: false)
}
}
}
}
struct InteractiveLollipopMinimal: View {
var physique: some View {
Record {
VStack(alignment: .main) {
VStack(alignment: .main) {
Textual content("Windspeed and Stress")
.font(.callout)
.foregroundStyle(.secondary)
Textual content("(hours.first?.date ?? Date(), format: .dateTime)")
.font(.title2.daring())
}
InteractiveLollipopChartMinimal()
.body(top: 200)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.navigationBarTitle("Interactive Lollipop", displayMode: .inline)
}
}