swiftswiftuichartsoverlaygesture

Swift charts - scrolling does not work while using .chartXSelection (or) .chartYSelection modifiers


I also tried using the .chartOverlay modifier and used the .onTapGesture modifier to get the point and the value. But the view, as expected, blocked the chart and thereby restricted the chart scroll behavior.

.chartOverlay(content: { proxy in
            GeometryReader { geometry in
                Rectangle()
                    .fill(.red.opacity(0.4))
                    .frame(width: 100, height: 100)
                    .onTapGesture(count: 1, coordinateSpace: .global) { value in
                        guard let plotFrame = proxy.plotFrame else { return }
                        let origin = geometry[plotFrame].origin
                        let location = CGPoint(
                            x: value.x - origin.x,
                            y: value.y - origin.y
                        )
                        // Get the x (date) and y (price) value from the location.
                        let (date, price) = proxy.value(at: location, as: (String, Double).self) ?? ("x", 10)
                        print("Location: \(date), \(price)")
                    }
                
            }
        })

Solution

  • A drag gesture on a Chart also counts as "selecting" the chart - for every bit of distance the finger moves, you are selecting a new value in the chart. This obviously interferes with scrolling.

    It seems like you only want taps to count as "selecting" the chart. You can use a chartGesture. Here is a complete example:

    struct Point: Hashable {
        let x: Double
        let y: Double
    }
    
    let data = (0..<100).map { Point(x: Double($0), y: .random(in: 0..<100)) }
    
    struct ContentView: View {
        @State private var selection: Double = 0
        
        var body: some View {
            VStack {
                Text("Selected: \(selection)")
                Chart {
                    LinePlot(data, x: .value("X", \.x), y: .value("Y", \.y))
                }
                .chartScrollableAxes(.horizontal)
                .chartXVisibleDomain(length: 10)
                .chartGesture { proxy in
                    SpatialTapGesture().onEnded { value in
                        if let newSelection = proxy.value(atX: value.location.x, as: Double.self) {
                            selection = newSelection
                        }
                    }
                }
            }
        }
    }