在 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"
}

在文档中,似乎有两种选择:

  1. tonexty - 填写如下。问题是 'tonexty' 有点限制 - 用例是 'filling until the line',因此阴影仅在 110 以上。示例:

  1. 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>