fco*_*llf 5 charts swiftui ios16 swiftui-charts
使用新的 SwiftUI Charts 框架,我们可以制作比可见屏幕更大的图表,并将其放入 ScrollView 中以使其可滚动。像这样的东西:
var body : some View {
GeometryReader { proxy in
ScrollView(.horizontal, showsIndicators: false) {
Chart {
ForEach(data) { entry in
// ...
}
}
.frame(width: proxy.size.width * 2)
}
}
}
Run Code Online (Sandbox Code Playgroud)
有谁知道是否可以以编程方式移动滚动以显示图表的特定区域?
我尝试过使用ScrollViewReader,在 x 轴标签处设置 ID,并尝试使用该scrollTo函数导航到任何这些位置,但没有成功:
Chart {
/// ...
}
.chartXAxis {
AxisMarks(values: .stride(by: .day)) { value in
if let date : Date = value.as(Date.self) {
Text(date, style: .date)
.font(.footnote)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个俗气的解决方法似乎可以解决问题。我将图表放入 ZStack 中,并用 HStack 覆盖图表。HStack 包含一堆符合 Identificable 协议的不可见对象。不可见物体的数量、ID 和位置与图表数据相符。
由于 ZStack 视图现在包含可识别的元素,ScrollViewReader 按预期工作。
import SwiftUI
import Charts
struct ChartData: Identifiable {
var day: Int
var value: Int
var id: String { "\(day)" }
}
struct ContentView: View {
@State var chartData = [ChartData]()
@State var scrollSpot = ""
let items = 200
let itemWidth: CGFloat = 30
var body: some View {
VStack {
ScrollViewReader { scrollPosition in
ScrollView(.horizontal) {
// Create a ZStack with an HStack overlaying the chart.
// The HStack consists of invisible items that conform to the
// identifible protocol to provide positions for programmatic
// scrolling to the named location.
ZStack {
// Create an invisible rectangle for each x axis data point
// in the chart.
HStack(spacing: 0) {
ForEach(chartData) { item in
Rectangle()
.fill(.clear)
// Setting maxWidth to .infinity here, combined
// with spacing:0 above, makes the rectangles
// expand to fill the frame specified for the
// chart below.
.frame(maxWidth: .infinity, maxHeight: 0)
// Here, set the rectangle's id to match the
// charted data.
.id(item.id)
}
}
Chart(chartData) {
BarMark(x: .value("Day", $0.day),
y: .value("Amount", $0.value),
width: 20)
}
.frame(width: CGFloat(items) * itemWidth, height: 300)
}
}
.padding()
.onChange(of: scrollSpot, perform: {x in
if (!x.isEmpty) {
scrollPosition.scrollTo(x)
scrollSpot = ""
}
})
}
.onAppear(perform: populateChart)
Button("Scroll") {
if let x = chartData.last?.id {
print("Scrolling to item \(x)")
scrollSpot = x
}
}
Spacer()
}
}
func populateChart() {
if !chartData.isEmpty { return }
for i in 0..<items {
chartData.append(ChartData(day: i, value: (i % 10) + 2))
}
}
}
Run Code Online (Sandbox Code Playgroud)
恕我直言,这应该可以在 SwiftUI 盒子之外工作。Apple 对初始化程序的注释是这么说的:creates a chart composed of a series of identifiable marks.所以...如果标记是可识别的,那么期望 ScrollViewReader 能够处理图表的标记并不夸张。
但是不!
人们希望这是 Apple 的疏忽,因为该框架是新的,并且他们将在即将发布的版本中公开图表标记的 id。
| 归档时间: |
|
| 查看次数: |
2567 次 |
| 最近记录: |