SwiftUI Scatter Charts
SwiftUI Charts support creating scatter charts. To create a scatter chart, use a `Chart` view and place `PointMark`s or `LineMark`s inside.
import SwiftUI import Charts struct SampleScatterChartView: View { @State private var startIndex: Int = 0 @State private var data: [CGPoint] = [] @State private var task: Task
? = nil var body: some View { Text("SwiftUI Scatter Chart") .font(.largeTitle) Text("Lissajous curves are nice") VStack { Grid { GridRow { Chart { ForEach(Array(0 ..< data.count), id: \.self) { index in let item = data[index] if index == data.count - 1 { PointMark( x: .value("x", Double(index)), y: .value("y", Double(item.y)) ) } LineMark( x: .value("x", Double(index)), y: .value("y", Double(item.y)) ) } } .chartXAxis { AxisMarks { AxisGridLine() AxisTick() } } .chartYAxis { AxisMarks { AxisGridLine() AxisTick() } } .padding(.horizontal, 8) .padding(.vertical, 8) .background { Color.white } .clipShape(RoundedRectangle(cornerRadius: 16)) Chart { ForEach(Array(0 ..< data.count), id: \.self) { index in let item = data[index] if index == data.count - 1 { PointMark( x: .value("x", Double(item.x)), y: .value("y", Double(item.y)) ) } LineMark( x: .value("x", Double(item.x)), y: .value("y", Double(item.y)) ) } } .chartXAxis { AxisMarks { AxisGridLine() AxisTick() } } .chartYAxis { AxisMarks { AxisGridLine() AxisTick() } } .padding(.horizontal, 8) .padding(.vertical, 8) .background { Color.white } .clipShape(RoundedRectangle(cornerRadius: 16)) } GridRow { Color.clear Chart { ForEach(Array(0 ..< data.count), id: \.self) { index in let item = data[index] if index == data.count - 1 { PointMark( x: .value("x", Double(item.x)), y: .value("y", Double(index)) ) } LineMark( x: .value("x", Double(item.x)), y: .value("y", Double(index)) ) } } .chartXAxis { AxisMarks { AxisGridLine() AxisTick() } } .chartYAxis { AxisMarks { AxisGridLine() AxisTick() } } .padding(.horizontal, 8) .padding(.vertical, 8) .background { Color.white } .clipShape(RoundedRectangle(cornerRadius: 16)) } } Spacer() } .padding() .background { Color(white: 0.9) } .onTapGesture { // for testing loadData() } .onAppear { loadData() } } private func loadData() { if task != nil { task?.cancel() } task = Task { let w1 = 0.2 let w2 = 0.3 let phi1 = 0.0 let phi2 = 0.0 for i in 0 ..< 1000 { do { try await Task.sleep(nanoseconds: 1_000_000 * 100) let x = (sin(Double(i) * w1 + phi1) + 1.0) * 0.5 let y = (sin(Double(i) * w2 + phi2) + 1.0) * 0.5 await MainActor.run { startIndex = i data.append(CGPoint(x: x, y: y)) if data.count > 50 { data.remove(at: 0) } } } catch { } } } } } #Preview { SampleScatterChartView() }
