我一直在研究时间序列的面积图,该时间序列在零上下紧密悬停。我需要我已经实现的缩放和焦点/工具提示功能。您可以拖动选择图表的一个区域,它会放大。双击缩小。
我想使用浅蓝色到深蓝色的线性渐变来强调离零最远的值。我设法将它添加到零以上的值(0 到 yMax)。
我怎么能对称地“镜像”负值的这种渐变效果?渐变在语义上应该是合乎逻辑的,例如这里描绘的 -0.5 的 yMin 应该具有大约 +0.5 的颜色级别,而不是 yMax。
我怎样才能将渐变应用于线条笔划?
如何避免缩放时渐变扭曲?
https://stackblitz.com/edit/angular-deviation-chart-gradient

为此,我改变了两件事。首先是使渐变跨越图表线“下方”的整个区域。它跨越 的最低值和最高值y。
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", 0).attr("y1", y(d3.min(data, (d) => d[1])))
.attr("x2", 0).attr("y2", y(d3.max(data, (d) => d[1])))
Run Code Online (Sandbox Code Playgroud)
接下来要做的是修改渐变的停靠点。它是一个从最低y值到最高y值的梯度。停靠点设置为:
因此我在另一种方法中设置停止
.selectAll("stop")
.data(this.getGradientData())
Run Code Online (Sandbox Code Playgroud)
...并且该方法是这样编写的
getGradientData(): Array<T> {
const dataMaxValue = Math.max(...this.data.map(element => element[1]));
const dataMinValue = Math.min(...this.data.map(element => element[1]));
const valuesSpan = dataMaxValue - dataMinValue;
if (Math.abs(dataMaxValue) > Math.abs(dataMinValue)) {
const shorterPartToLongerPartRatio = Math.abs(dataMinValue) / Math.abs(dataMaxValue);
const shorterPartToWholeRatio = Math.abs(dataMinValue) / valuesSpan;
return [
{offset: "0%", color: `rgba(0, 0, 0, ${shorterPartToLongerPartRatio})`},
{offset: `${shorterPartToWholeRatio * 100}%`, color: 'lightblue'},
{offset: "100%", color: "black"}
];
}
const shorterPartToLongerPartRatio = Math.abs(dataMaxValue) / Math.abs(dataMinValue);
const shorterPartToWholeRatio = Math.abs(dataMaxValue) / valuesSpan;
return [
{offset: "0%", color: 'black'},
{offset: `${100 - (shorterPartToWholeRatio * 100)}%`, color: 'lightblue'},
{offset: "100%", color: `rgba(0, 0, 0, ${shorterPartToLongerPartRatio})`}
];
Run Code Online (Sandbox Code Playgroud)
}
请注意我是如何更改darkblue为black. 当背景为白色时,这是一种找到成比例颜色值(具有不透明度)的简单方法。这可以通过计算所需的颜色来改进。
即使负值大于正值,该解决方案也应该有效。这是修改后的示例:https : //stackblitz.com/edit/angular-deviation-chart-gradient-zrghr2
@Edit:至于在缩放时避免梯度失真的问题。不幸的是,您无法阻止这种情况。这是一个像计算机图形一样古老的问题,原因是没有足够的颜色可用:)
@Edit2:寻找中间色的方法相当简单:
getIntermediateColor(colorOneRGB, colorTwoRGB, ratio) {
const newR = colorOneRGB[0] + (colorTwoRGB[0] - colorOneRGB[0]) * ratio;
const newG = colorOneRGB[1] + (colorTwoRGB[1] - colorOneRGB[1]) * ratio;
const newB = colorOneRGB[2] + (colorTwoRGB[2] - colorOneRGB[2]) * ratio;
return `rgb(${newR}, ${newG}, ${newB})`;
}
Run Code Online (Sandbox Code Playgroud)