简体   繁体   English

无论如何,在 SwiftUI 中是否可以检测 `BarMark` 上的悬停手势?

[英]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.我正在尝试实现一种方法来检测 SwiftUI 中Chart上的悬停手势。

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 .起初我尝试向BarMark添加.onHover()修饰符,如下所示,但它似乎不起作用,因为BarMark不符合View Protocol 而.onHover()定义为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?那么这是否意味着如果我想在图表上显示用户 hover 时的其他数据,那么我必须创建自己的图表而不是使用Chart框架中的Charts

You could try this approach, using an .chartOverlay and .onContinuousHover .您可以使用.chartOverlay.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如果您只想点击BarMarks ,请参阅我的其他答案: 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.尝试创建一个包装BarMark并符合View协议的自定义视图,然后为这个自定义视图添加onHover()修饰符。

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.或者,您可以结合使用 SwiftUI 视图和手势识别器来创建自己的图表,并使用onHover()修饰符或HoverGesture来检测用户何时将鼠标悬停在图表的特定区域上。

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.在任何情况下,您都必须创建自己的图表,这会涉及更多工作,但也会让您更好地控制图表的外观和行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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