SwiftUI Chart 拖动选区的透明度为何随数据点数量变化?
将 RectangleMark 移出 ForEach,整个 Chart 就只会绘制一个选区矩形,透明度也不会再因数据点数量增加而叠加。拖动时继续更新 dragRange 即可。
为什么数据点数量会影响透明度?
当前代码将 RectangleMark 放在 ForEach 内。只要 dragRange 不为 nil,每个数据点都会创建一个矩形。这些矩形的坐标完全相同,因此会重叠。
.opacity(0.05) 设置的是单个矩形的不透明度。按照通常的 alpha 合成方式,如果 n 个同色矩形完全重叠,每个矩形的不透明度为 a,合成后的不透明度为:
A = 1 - (1 - a)^n
重复绘制通常会让绿色区域更浓、更不透明。问题中描述的“更透明”与这个叠加方向相反,但从给出的代码可以确定,选区矩形会随着数据点数量增加而重复创建。
如何修改代码?
将原来的 Chart { ... } 内容替换为下面的结构。后面的 .chartXSelection(range:) 和 .chartOverlay 可以继续沿用原代码:
Chart {
if let dragRange {
RectangleMark(
xStart: .value("x", dragRange.lowerBound),
xEnd: .value("x", dragRange.upperBound),
yStart: .value("y", 1),
yEnd: .value("y", 9)
)
.foregroundStyle(.green.opacity(0.05))
}
ForEach(Array(zip(numbers, numbers.indices)), id: \.0) { number, index in
LineMark(
x: .value("Index", index),
y: .value("Value", number)
)
}
}
这里的 if let dragRange 只创建一个选区矩形,ForEach 则创建折线的数据标记。增加数据点不会再增加选区矩形的数量。
还需要注意什么?
0.05 是一个很低的不透明度。修正重复绘制后,选区可能比之前淡,因为现在只有一个矩形使用这个数值。可以根据需要调整这个固定值。
示例保留了原来的 yStart: 1 和 yEnd: 9,所以选区只覆盖这个 y 值区间。是否覆盖整个绘图区是另一个显示需求,不影响此次透明度问题的修复。
原代码还使用数据值作为 ForEach 的 ID,即 id: \.0。如果数据可能重复,标识就可能不唯一。对于这里按数组下标绘制的示例,也可以改用:
ForEach(numbers.indices, id: \.self) { index in
LineMark(
x: .value("Index", index),
y: .value("Value", numbers[index])
)
}
这个调整可以避免重复数据值造成的标识问题;解决选区透明度变化仍需将 RectangleMark 移出循环。
备注:内容仅供参考。
