SwiftUI 图表可点击注释

ank*_*ara 1 ios swiftui swiftui-charts

我正在尝试处理 SwiftUI BarMark 中注释的点击

var body: some View {
       List {
           Chart {
               ForEach(data) {
                   BarMark(
                       x: .value("Mount", $0.mount),
                       y: .value("Value", $0.value)
                   )
                   .foregroundStyle(by: .value("Type", "Series \($0.type)"))
                   .position(by: .value("Type", $0.type))
                   .annotation {
                       HStack {
                           Rectangle()
                               .fill(Color.red.opacity(0.2))
                               .frame(width: 20, height: 20)
                               .clipShape(Circle())
                               .onTapGesture {
                                   print("Tapped!") // Never called
                               }
                       }
                   }
               }
           }
           .frame(height: 250)
           .labelsHidden()
       }
   }
Run Code Online (Sandbox Code Playgroud)

我还尝试了带有操作、图像等的按钮,但似乎注释中的所有交互都被禁用或者我不知道..

苹果提供了一些用于点击句柄的代码,但我不知道如何将其用于字符串(例如苹果有日期)并且没有像我一样的比较栏。

有什么想法吗?

在此输入图像描述

小智 6

图表似乎被设计为只是一个扁平化视图,没有任何交互。如果你想与图表的元素交互,你必须使用

.chartOverlay()

此函数覆盖图表上的视图,然后您必须使用 GeometryReader 才能找到与之交互的特定位置。

以下是 Apple 文档中的示例

Chart(data) {
  LineMark(
    x: .value("date", $0.date),
    y: .value("price", $0.price)
  )
}
.chartOverlay { proxy in
  GeometryReader { geometry in
    Rectangle().fill(.clear).contentShape(Rectangle())
        .gesture(
            DragGesture()
                .onChanged { value in
                    // Convert the gesture location to the coordiante space of the plot area.
                    let origin = geometry[proxy.plotAreaFrame].origin
                    let location = CGPoint(
                        x: value.location.x - origin.x,
                        y: value.location.y - origin.y
                    )
                    // Get the x (date) and y (price) value from the location.
                    let (date, price) = proxy.value(at: location, as: (Date, Double).self)
                    print("Location: \(date), \(price)")
                }
        )
}
Run Code Online (Sandbox Code Playgroud)

}

所以对于你的例子来说,它会是这样的:

Chart {
   ForEach(data) {
       BarMark(
          x: .value("Mount", $0.mount),
          y: .value("Value", $0.value)
       )
   }
}
.chartOverlay { proxy in
  GeometryReader { geometry in
    Rectangle().fill(.clear).contentShape(Rectangle())
      .onTapGesture { location in
        guard let value: (mount, value) = proxy.value(at: location)    else  {
           return
        }
        //Check if value is included in the data from the chart
        print("Tapped!")
      }
   }
}
Run Code Online (Sandbox Code Playgroud)