plotly.js
plotly.js copied to clipboard
Inconsistent EventData for axis range
Version used: plotly.js (basic) v1.28.3
I am registered to the event "plotly_relayout". I am using a chart with one trace and a rangeslider.
When zooming / panning on the trace, the following eventData is emitted to my callback:
Object {xaxis.range[0]: "2017-04-25 02:03:12.3635", xaxis.range[1]: "2017-05-24 12:21:05.5226"}
When panning on the rangeslider the follwoing eventData is emitted to my callback:
Object {xaxis.range: Array[2]}
And the array contains: ["2017-05-16 11:13:38.5694", "2017-06-14 21:31:31.7285"]
The plotly documentation shows that you are supposed to access the eventData axis information like this: eventdata['xaxis.range[0]']
this only works for the first object, not the one emitted when using the rangeslider.
Thanks for pointing this out.
Callbacks emitting Object {xaxis.range: Array[2]}
are still valid as
Plotly.relayout(gd, 'xaxis.range', [0, 1])
// is equivalent to
Plotly.relayout(gd, {'xaxis.range[0]': 0, 'xaxis.range[1]': 1})
But, I agree we should standardise our event data. For more on this topic, see https://github.com/plotly/plotly.js/issues/168.
To me, Object {xaxis.range: Array[2]}
seems more user friendly, as some users might not be accustomed to out nested property attribute string (e.g. 'xaxis.range[0]'
).
The plotly documentation shows that you are supposed to access the eventData axis information like this: eventdata['xaxis.range[0]']
Where do you see this exactly?
We won't be able to fix this in v1.x
I'm afraid as this would be a breaking change, but we'll for sure come up with a solution in v2
.
I got this from:
https://plot.ly/javascript/zoom-events/
From the example:
'x-axis start:' + eventdata['xaxis.range[0]'] + '\n' +
'x-axis end:' + eventdata['xaxis.range[1]'] );
My workaround (within the plotly_relayout callback):
var range = eventdata['xaxis.range[0]']; if (range === undefined) { range = eventdata['xaxis.range'][0]; }
Why is this closed? It's a bug. I also get an object with keys 'xaxis.range[0]' and 'xaxis.range[1]' in the onRelayout callback. Quite daft.
I just came across this bug while using the plotly_relayout callback too.
When zooming in on a plot the event data I get is:
{xaxis.range[0]: 0.20859375, xaxis.range[1]: 0.265625, yaxis.range[0]: 124.36153675327559, yaxis.range[1]: 346.435709526982}
if I double click to zoom out the event data I get is:
{xaxis.autorange: true, yaxis.autorange: true}
If I just resize the plot, the event data comes back as a proper object:
{width: 705
height: 327
legend: {orientation: "h"}
margin: {t: 25, b: 35, l: 25, r: 25, pad: 5}
showlegend: true
xaxis: {rangemode: "tozero", showgrid: true, showspikes: false, spikethickness: 1}
yaxis: {automargin: true, rangemode: "tozero", showgrid: true, showspikes: false, spikethickness: 1}
}
Ideally, the event data would always return an object with nested properties ie:
{ xaxis: { range: [ 0.20859375, 0.265625] },
yaxis: { range: [124.36153675327559, 346.435709526982] }
}
or
{xaxis: {autorange: true}, yaxis: {autorange: true }}
The plotly_relayout
event data mirrors the Plotly.relayout
input arguments - so nested objects are not an option, as this would overwrite far more than you want changed if passed back to Plotly.relayout
- any other settings inside xaxis
or yaxis
would be cleared.
And for reference, the reason we tended to use {'xaxis.range[0]': x0, 'xaxis.range[1]': x1}
rather than {'xaxis.range': [x0, x1]}
is that you can drag or edit a single end an axis, by clicking or dragging near the end of one of the axes - then it would be incorrect to say the user changed both items in xaxis.range
, and there's no way to represent that with the {'xaxis.range': [x0, x1]}
form.
You can access the full gd.layout
object from inside the plotly_relayout
event handler, it will have been updated by the time the event is emitted.
Sorry, but why is this closed?
I still get {'xaxis.range[0]': x0, 'xaxis.range[1]': x1}
when zooming in, but {'xaxis.range': [x0, x1]}
when resetting the axes (by double clicking).
For the sake of keeping things uniform, my workaround is currently:
var xaxis_range = eventData['xaxis.range'];
eventData['xaxis.range[0]'] = xaxis_range[0];
eventData['xaxis.range[1]'] = xaxis_range[1];
}```