admaDIC App Development & IT Solutions

SwiftUI Scatter Charts

by Annett Schwarze | 2025-06-06

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()
}
SwiftUI Scatter Chart

 

www.admadic.de | webmaster@admadic.de | Legal Notice and Trademarks | Privacy
© 2005-2007 - admaDIC | All Rights Reserved
All other trademarks and/or registered trademarks are the property of their respective owners
Last Change: Fri Jun 6 09:31:03 2025 GMT