简体   繁体   中英

Is there anyway to detect hovering gesture on `BarMark` in SwiftUI?

I'm trying to implement a way to detect hovering gesture on Chart in SwiftUI.

At first I tried adding .onHover() modifier to BarMark like below, but it seems it doesn't work because BarMark does not conform to View Protocol while .onHover() is defined View .

Chart(modules) { module in
          BarMark(x: .value("name", module.name), y: .value("Score", module.score)).onHover { over in
             details = module.name
     } // gives error
}

So does that mean If I want to show additional data when user hover over the Chart graph, then I have to create my own Chart graph rather than using Chart from Charts framework?

You could try this approach, using an .chartOverlay and .onContinuousHover . You will have to adjust the location calculations to suit your purpose.

struct ContentView: View {
    let measurement: [Measurement] = [
        Measurement(id: "1", val: 11.2),
        Measurement(id: "2", val: 22.2),
        Measurement(id: "3", val: 38.2)
    ]
    
    @State var select = "0"
    @State var isHovering = false
    
    var body: some View {
        Chart {
            ForEach(measurement) { data in
                BarMark(x: .value("Time", data.id), y: .value("val", data.val))
                    .foregroundStyle(select == data.id ? .blue : .red)
            }
        }
        .chartOverlay { proxy in
            GeometryReader { geometry in
                ZStack(alignment: .top) {
                    Rectangle().fill(.clear).contentShape(Rectangle())
                        .onContinuousHover { phase in
                            switch phase {
                            case .active(let location):
                                bar(at: location, proxy: proxy, geometry: geometry)
                                isHovering = true
                            case .ended:
                                isHovering = false
                            }
                        }
                }
            }
        }
    }
    
    func bar(at location: CGPoint, proxy: ChartProxy, geometry: GeometryProxy) {
        let xPosition = location.x - geometry[proxy.plotAreaFrame].origin.x
        let yPosition = location.y - geometry[proxy.plotAreaFrame].origin.y
        guard let month: String = proxy.value(atX: xPosition) else { return }
        guard let measure: Double = proxy.value(atY: yPosition) else { return }
        // more logic here ....
        select = month
    }
}

struct Measurement: Identifiable {
    var id: String
    var val: Double
}

If you want to just tap on the BarMarks , see my other answer at: How to change the color of BarView in SwiftUI charts when we tap on it

Try to create a custom view that wraps the BarMark and conforms to the View protocol, and then add the onHover() modifier to this custom view.

Alternatively, you could create your own chart using a combination of SwiftUI views and gesture recognizers, and use the onHover() modifier or a HoverGesture to detect when the user is hovering over a specific area of the chart.

In any case, you would have to create your own chart, which would involve more work, but it would also give you more control over the appearance and behavior of the chart.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM