SwiftUI中可滚动可点击堆叠柱状图的交互问题
解决SwiftUI可滚动堆叠柱状图的柱子点击问题
方案一:直接为单个柱子绑定点击手势
放弃全局GeometryReader的位置检测逻辑,直接在构建BarMark时为每个柱子添加点击手势。这种方式完全适配图表滚动场景,因为手势绑定在柱子自身的视图上,滚动时点击区域会跟随柱子同步移动。
示例代码:
// 假设你的数据模型结构如下 struct ChartItem: Identifiable { let id = UUID() let name: String var value: Int } @State private var data: [ChartItem] = [] @State private var showingEditView = false @State private var selectedItem: ChartItem? // 构建可滚动柱状图 Chart(data) { item in BarMark( x: .value("名称", item.name), y: .value("数值", item.value) ) .onTapGesture { // 触发点击逻辑,选中当前柱子并弹出修改视图 selectedItem = item showingEditView = true } } .chartScrollableAxes(.horizontal) // 开启水平滚动 .sheet(isPresented: $showingEditView, item: $selectedItem) { item in // 这里放置你的数值修改子视图 EditItemView(item: item) }
方案二:修复chartOverlay的坐标转换问题
如果必须保留chartOverlay的全局点击检测方式,需要通过图表代理的transform方法,将点击位置转换为图表内部的坐标系统(抵消滚动偏移的影响)。
修改后的代码:
.chartOverlay { proxy in GeometryReader { geometry in Color.clear .contentShape(Rectangle()) .onTapGesture { location in // 转换点击坐标到图表内部坐标系 let chartLocalLocation = proxy.transform(location, from: geometry) // 获取对应的数据 if let (value, name) = proxy.value(at: chartLocalLocation, as: (Int, String).self) { print("点击柱子:\(name),当前数值:\(value)") // 这里添加弹窗或其他交互逻辑 } } } } .chartScrollableAxes(.horizontal)
方案对比
- 方案一逻辑简洁,直接绑定数据模型,无需处理坐标转换,是优先推荐的实现方式。
- 方案二更适合需要全局点击区域(比如点击柱子外区域也要响应)的场景,或无法直接为
BarMark添加手势的特殊情况。
内容的提问来源于stack exchange,提问作者Cooper H
相关产品推荐
相关产品推荐

