在 PlotlyJS 中的特定 Y 值上方填充/阴影图表
Fill / Shade a chart above a specific Y value in PlotlyJS
我想在 PlotlyJS 中填充到特定的 Y 值。这是我从 PlotlyJS 文档中得到的:Fiddle
{
"x": [
"2016-01-31T00:03:57.000Z",
"2016-02-12T04:35:26.000Z"
],
"y": [
100,
100
],
"fill": "tonexty",
"fillcolor": "#8adcb3"
}
在文档中,似乎有两种选择:
tonexty
- 填写如下。问题是 'tonexty' 有点限制 - 用例是 'filling until the line',因此阴影仅在 110 以上。示例:
tozeroy
- 填充到零:
此外,您是否需要引入新轨迹才能创建填充?
这意味着 if I have a chart as follows (with only one trace but a threshold line as a shape):我需要引入另一个轨迹 只是为了创建一个填充 。也许我在文档中遗漏了什么,或者这完全是错误的方法。
那么,如何在 PlotlyJS 中填充特定 Y 值上方的轨迹区域?
一个解决方案是使用多个跟踪。
在大于 0 的和不大于 0 的轨迹之间拆分所有轨迹。
完成后,您可以用 'tozeroy' 值填充(或不填充)。
following jsfiddle 显示了一个工作示例。
代码如下:
HTML:
<div id="myDiv" style="width:600px;height:250px;"></div>
JS:
var data = [
{
x: ['A', 'B', 'C', 'D'],
y: [1, 3, 6, 0],
fill: 'tozeroy',
fillcolor: '#8adcb3'
},
{
x: ['D', 'F', 'G', 'I'],
y: [0, -3, -2, 0],
fill: 'toself'
},
{
x: ['I', 'J', 'K'],
y: [0, 5, 7],
fill: 'tozeroy',
fillcolor: '#0adcb3'
}
];
Plotly.newPlot('myDiv', data);
结果如下:
这是另一个利用 Plotly 的 fill: "toself"
的解决方案。这个想法是创建一个封闭的线轨迹,它包围阈值以上的区域和主线的标记。适用于零以上的阈值和数字 x 值。
辅助迹线隐藏了它们的图例,并与主迹线组合在一起,从而防止在切换图例时出现难看的伪影。
函数检查每个 x-y 对的 y 值是否高于阈值,如果是
- 检查是否已经有一个段高于阈值并使用这个或创建一个新的段
- 分段从阈值的 y 值开始,从阈值以上的点和之前的点开始的中间 x 值。
- 每个段都以等于阈值的 y 值和等于段中最后一个点和下一个点的平均值的 x 值终止
函数本身当然可以用更好的方式编写,但这只是概念验证。
function dataToTraces(data, threshold) {
var fillers = [];
var emptyFiller = {
x: [],
y: [],
fill: "toself",
mode: "lines",
line: {
width: 0
},
opacity: 0.5,
fillcolor: "#8adcb3",
showlegend: false,
legendgroup: "main"
}
fillers.push(emptyFiller);
for (var i = 0; i < data.y.length; i += 1) {
if (data.y[i] >= threshold) {
if (i !== 0 && data.y[i - 1] < threshold) {
fillers[fillers.length - 1].x.push(data.x[i - 1] + (threshold - data.y[i - 1]) / (data.y[i] - data.y[i - 1]));
fillers[fillers.length - 1].y.push(threshold);
}
fillers[fillers.length - 1].x.push(data.x[i]);
fillers[fillers.length - 1].y.push(data.y[i]);
} else if (fillers[fillers.length - 1].x.length > 0) {
if (i !== 0 && data.y[i - 1] !== threshold) {
fillers[fillers.length - 1].x.push(data.x[i - 1] + (threshold - data.y[i - 1]) / (data.y[i] - data.y[i - 1]));
fillers[fillers.length - 1].y.push(threshold);
}
fillers.push(emptyFiller);
}
}
return fillers;
}
var data = [{
x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
y: [1, 3, 6, 2, -1, 5, 1, 3, 0],
name: "main",
legendgroup: "main"
}];
var fillers = dataToTraces(data[0], 2);
Plotly.newPlot("myDiv", data.concat(fillers));
<div id="myDiv"></div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
我想在 PlotlyJS 中填充到特定的 Y 值。这是我从 PlotlyJS 文档中得到的:Fiddle
{
"x": [
"2016-01-31T00:03:57.000Z",
"2016-02-12T04:35:26.000Z"
],
"y": [
100,
100
],
"fill": "tonexty",
"fillcolor": "#8adcb3"
}
在文档中,似乎有两种选择:
tonexty
- 填写如下。问题是 'tonexty' 有点限制 - 用例是 'filling until the line',因此阴影仅在 110 以上。示例:
tozeroy
- 填充到零:
此外,您是否需要引入新轨迹才能创建填充?
这意味着 if I have a chart as follows (with only one trace but a threshold line as a shape):我需要引入另一个轨迹 只是为了创建一个填充 。也许我在文档中遗漏了什么,或者这完全是错误的方法。
那么,如何在 PlotlyJS 中填充特定 Y 值上方的轨迹区域?
一个解决方案是使用多个跟踪。
在大于 0 的和不大于 0 的轨迹之间拆分所有轨迹。
完成后,您可以用 'tozeroy' 值填充(或不填充)。
following jsfiddle 显示了一个工作示例。
代码如下:
HTML:
<div id="myDiv" style="width:600px;height:250px;"></div>
JS:
var data = [
{
x: ['A', 'B', 'C', 'D'],
y: [1, 3, 6, 0],
fill: 'tozeroy',
fillcolor: '#8adcb3'
},
{
x: ['D', 'F', 'G', 'I'],
y: [0, -3, -2, 0],
fill: 'toself'
},
{
x: ['I', 'J', 'K'],
y: [0, 5, 7],
fill: 'tozeroy',
fillcolor: '#0adcb3'
}
];
Plotly.newPlot('myDiv', data);
结果如下:
这是另一个利用 Plotly 的 fill: "toself"
的解决方案。这个想法是创建一个封闭的线轨迹,它包围阈值以上的区域和主线的标记。适用于零以上的阈值和数字 x 值。
函数检查每个 x-y 对的 y 值是否高于阈值,如果是
- 检查是否已经有一个段高于阈值并使用这个或创建一个新的段
- 分段从阈值的 y 值开始,从阈值以上的点和之前的点开始的中间 x 值。
- 每个段都以等于阈值的 y 值和等于段中最后一个点和下一个点的平均值的 x 值终止
函数本身当然可以用更好的方式编写,但这只是概念验证。
function dataToTraces(data, threshold) {
var fillers = [];
var emptyFiller = {
x: [],
y: [],
fill: "toself",
mode: "lines",
line: {
width: 0
},
opacity: 0.5,
fillcolor: "#8adcb3",
showlegend: false,
legendgroup: "main"
}
fillers.push(emptyFiller);
for (var i = 0; i < data.y.length; i += 1) {
if (data.y[i] >= threshold) {
if (i !== 0 && data.y[i - 1] < threshold) {
fillers[fillers.length - 1].x.push(data.x[i - 1] + (threshold - data.y[i - 1]) / (data.y[i] - data.y[i - 1]));
fillers[fillers.length - 1].y.push(threshold);
}
fillers[fillers.length - 1].x.push(data.x[i]);
fillers[fillers.length - 1].y.push(data.y[i]);
} else if (fillers[fillers.length - 1].x.length > 0) {
if (i !== 0 && data.y[i - 1] !== threshold) {
fillers[fillers.length - 1].x.push(data.x[i - 1] + (threshold - data.y[i - 1]) / (data.y[i] - data.y[i - 1]));
fillers[fillers.length - 1].y.push(threshold);
}
fillers.push(emptyFiller);
}
}
return fillers;
}
var data = [{
x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
y: [1, 3, 6, 2, -1, 5, 1, 3, 0],
name: "main",
legendgroup: "main"
}];
var fillers = dataToTraces(data[0], 2);
Plotly.newPlot("myDiv", data.concat(fillers));
<div id="myDiv"></div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>