plotly / plotly.js

Open-source JavaScript charting library behind Plotly and Dash
https://plotly.com/javascript/
MIT License
16.83k stars 1.85k forks source link

enable tonexty without fallback to tozeroy #5538

Open ghost opened 3 years ago

ghost commented 3 years ago

In our use case, we are plotting quantiles of a data set, with lower and upper bound as well as the median. For convenience, we need to fill in the area between the upper and lower bound shown.

The way we have solved this is by setting fill_type=tonexty on all traces and fill_color=gray on the top four traces, but fill_color=None on the bottom trace.

It looks like this:

scatter all visible

The problem is if a user disables the bottom trace, the tonexty fill of the second-to-last trace falls back to tozeroy:

scatter one hidden

This makes no sense in our case. The expected/intended behavior is:

scatter one hidden expected

We have tried/considered several methods:

  1. Creating a stackgroup; this does allow a fill 'inside' the group only, but requires the trace values to be stacked, which they fundamentally aren't; hiding a trace in that case moves the traces above, which is incorrect.
  2. Disabling the trace toggle; this hides the problem of course, but it also disables a useful feature
  3. Dynamically changing the fill_colors when a trace is hidden; this might work, but I can't find an event to hook into, and since we are using Dash, doing this kind of hacking between Python and clientside callbacks is nontrivial at best.

The best solution would be a fill_type that fills to next but falls back to no fill.

alexcjohnson commented 3 years ago

This is a good idea, thanks @jenrol! For reference, the rationale for tonexty falling back on filling to zero is so you can build up a stacked area chart using only tonexty fill. But you're right, for non-stacked data this doesn't make much sense.

One workaround you can use until there's a built-in solution is to create a dummy first trace that's hidden from the legend, so whatever trace is next tries to fill to that and gives up: {x: [null], y: [null], showlegend: false} https://codepen.io/alexcjohnson/pen/ZEBmYqq?editors=0010 Screen Shot 2021-03-09 at 8 46 53 AM Screen Shot 2021-03-09 at 9 03 27 AM