I would like to fill until a specific Y value in PlotlyJS. This is as far as I got from the PlotlyJS docs: Fiddle
{
"x": [
"2016-01-31T00:03:57.000Z",
"2016-02-12T04:35:26.000Z"
],
"y": [
100,
100
],
"fill": "tonexty",
"fillcolor": "#8adcb3"
}
In the documentation, there seems to be two options:
tonexty
- Fills as below. The problem is 'tonexty' is a bit limiting - The use case is 'filling until the line', so shading ONLY above 110. Example:tozeroy
- Fills till zero:Also, do you need to introduce a new trace in order to create a fill?
This means that if I have a chart as follows (with only one trace but a threshold line as a shape): I need to introduce another trace just to create a fill. Maybe there's something I missed in the docs, or this is the wrong approach altogether.
So, how do you fill an area in a trace above a specific Y value in PlotlyJS?
A solution is to use multiple traces.
Split all your traces between ones which are above 0 and ones which are not.
When you are done you can fill them (or not) with the 'tozeroy' value.
The following jsfiddle shows a working example.
The code is as following :
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);
The result looks as following :
Here is another solution exploiting Plotly's fill: "toself"
. The idea is to create a closed line trace which encloses the area above the threshold and the markers of the main line. Works for threshold values above zero and for numerical x-values.
The helper traces have their legend hidden and are grouped with the main trace, thereby preventing ugly artifacts when toggling the legend.
The function checks for each x-y-pair if the y-value is above the threshold, if yes
The function itself can be surely written in a nicer way but it's just a proof-of-concept.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With