0

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)
    }
}

1 Answer 1

1

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)
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, this works. I kept my example simple, and in the complete chart there are also tickmarks and labels. I guess I would have to draw those also in the chartOverlay?
@koen You don't have to. AxisTick and AxisValueLabel doesn't interfere with this.
For completeness, chartYAxisLabel is also moving, so I am now drawing these in the chartOverlay as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.