如何在 iOS 16.0 的 Swift Charts 中的折线图上配置轴并设置显式轴起点和终点

Tah*_*zam 4 swift swiftui ios16

在此代码中,我声明一个图表,其 x 比例域位于两个双精度数之间:

Chart(points, id: \.self) { point in
    LineMark(
        x: .value("time/s", point.timestamp),
        y: .value("potential/mV", point.potential)
    )
    .foregroundStyle(by: .value("Electrode", point.electrode.symbol))
}
.chartXScale(domain: timeWindow)
// ...
Run Code Online (Sandbox Code Playgroud)

其中timeWindow声明如下:

var timeWindow: ClosedRange<Double> {
    doc.contents.time(at: window.lowerBound)...doc.contents.time(at: window.upperBound)
}
Run Code Online (Sandbox Code Playgroud)

time定义为:

func time(at index: Int) -> Double {
    return Double(index) * (1 / sampleRate)
}
Run Code Online (Sandbox Code Playgroud)

然而,生成的图表 x 轴在我提供的下限和上限处没有起点和终点ClosedRange<Double>,而是在图的左侧和右侧有一段神秘空间:

LineMark 图右侧图表中的空白区域。

如何使图表遵循我提供的域(边界也显示在底部工具栏工具栏项目组的文本视图中,使用代码Text("\(timeWindow.lowerBound.format()) s to \(timeWindow.upperBound.format()) s"))?如何让 y 轴呈现在图表左侧?

Tah*_*zam 5

解决方案是创建一个值数组,通过使用以下方法来构建轴内容AxisMarks

var xValues: [Double] {
    stride(from: timeWindow.lowerBound, to: timeWindow.upperBound, by: (timeWindow.upperBound - timeWindow.lowerBound) / 5).map { $0 }
}
Run Code Online (Sandbox Code Playgroud)

然后在图表修改器中:

Chart(points, id: \.self) { point in
    LineMark(
        x: .value("time/s", point.timestamp),
        y: .value("potential/mV", point.potential)
    )
    .foregroundStyle(by: .value("Electrode", point.electrode.symbol))
}
.chartXScale(domain: ClosedRange(uncheckedBounds: (lower: timeWindow.lowerBound, upper: timeWindow.upperBound)))
.chartXAxis {
    AxisMarks(values: xValues)
}
    \\ ...
Run Code Online (Sandbox Code Playgroud)

注意:我发现仍然需要包含修饰符chartXScale(domain:),否则 x 轴似乎总是从零开始,即使它不包含在轴标记中。

这会产生“可滚动”图的预期行为:

预期的可滚动情节。

然而,现在有一个缺点,即失去了确定轴中标记间距的自动方法,但这是我必须处理的折衷方案,并构造一个更好的算法来创建它们,而不是像上面使用的硬编码值5