swiftuiscrollableswiftui-charts

chartScrollableAxes moves axis


I am trying to implement a horizontal scrollable chart. However, the y axis moves along when scrolling. How can I make the y axis stay put?

Here is my code:

struct DataPoint: Identifiable {
    var id = UUID()
    let x: Double
    let y: Double
}

let minGlobalX: Double = 0
let maxGlobalX: Double = 100

let data: [DataPoint] = (Int(minGlobalX) ..< Int(maxGlobalX)).map { DataPoint(x: Double($0), y: Double(arc4random()) / Double(UInt32.max)) }

struct ContentView: View {
    var body: some View {
        Chart(data) {
            LineMark(
                x: .value("x", $0.x),
                y: .value("y", $0.y)
            )
            .lineStyle(StrokeStyle(lineWidth: 1))
        }
        .chartScrollableAxes(.horizontal)
        .chartXScale(domain: [minGlobalX, maxGlobalX])
        .chartXAxis {
            AxisMarks(position: .bottom, values: [0]) {
                AxisGridLine(stroke: .init(lineWidth: 1))
            }
        }
        .chartYScale(domain: [0, 1])
        .chartYAxis {
            AxisMarks(position: .leading, values: [0]) {
                AxisGridLine(stroke: .init(lineWidth: 1))
            }
        }
        .padding(20)
    }
}

Solution

  • The axis lines are just AxisGridLines positioned at the "0" position of the chart. When you scroll the chart, the "0" position moves, and so the line moves with it as well.

    You can add the lines using a chartOverlay instead. Position some 1-wide Rectangles using ChartProxy.plotContainerFrame:

    .chartOverlay { proxy in
        GeometryReader { geo in
            let plotContainer = geo[proxy.plotContainerFrame!]
            Rectangle()
                .frame(width: 1, height: plotContainer.height)
                .offset(x: plotContainer.minX, y: plotContainer.minY)
            Rectangle()
                .frame(width: plotContainer.width, height: 1)
                .offset(x: plotContainer.minX, y: plotContainer.maxY)
        }
    }