plotly.js: wishlist for potential breaking changes since v1

Leave this text box for planned improvements

  • upgrade d3 to v4.0.0 (now v5) - should be mostly a matter of updating the general update pattern.
  • remove es-promise polyfill from bundle - and thus make IE users add their own Promise polyfill.
  • drop jQuery event support
  • Make components (e.g. Annotations, Shapes, RangeSlider, …) register-able and remove them from the core bundle.
  • revamp set of default colorscales
  • make config arguments consistent https://github.com/plotly/plotly.js/issues/839
  • remove config.plot3dPixelRatio map for backward compatibility
  • Incorporate /remove all unofficial exposed methods (i.e Plotly.Plots, Plotly.Fx, Plotly.Snapshot, Plotly.PlotSchema, Plotly.Queue)
  • drop event-based Plotly.Snapshot.toImage and merge src/snapshot in plot_api/to_image.js
  • remove (some) components for lib/core.js - see https://github.com/plotly/plotly.js/pull/845
  • drop Plotly.relayout handlers for the 'remove' and 'add' special values - see https://github.com/plotly/plotly.js/pull/1086
  • for log axes, have layout express everything in data units instead of linearized units. This applies to range, tick0, and annotation and image positions.
  • remove support for dates provided as epoch milliseconds
  • remove the distinction between axis name and axis id (ie xaxis2 vs x2) probably by only using the name.
  • rename current gl marker symbol 'cross' -> 'cross-thin' (i.e. revert https://github.com/plotly/plotly.js/pull/1482/commits/c0eb06599db481f2137ed97e79bab5cb2bc31351)

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 12
  • Comments: 63 (51 by maintainers)

Most upvoted comments

On my list:

  • Incorporate /remove all unofficial exposed methods (i.e Plotly.Plots, Plotly.Fx, Plotly.Snapshot, Plotly.PlotSchema, Plotly.Queue)
  • Use proper state object instead of storing state in graph DOM element.
  • Add OO API e.g :
var plot = Plotly.createPlot('graph', data, layout, config);

plot.restyle(/* */);
plot.relayout(/* */);
plot.resize();
// ...
  • Drop jQuery event support
  • Better, more-consistent events data
  • Better, more-consistent config options

Remove our es6-promise polyfill and ask IE9, IE8, IE11 (ref) to use their own Promise polyfills.

Ooooooh boy.

  • use only d3 modules we need (fingers crossed)
  • standardize interfaces across all traces/plots
  • svg/gl parity
  • no DOM state (virtual dom + diffing would be awesomeeeee)
  • discrete process/render modules.
  • immutable plot state (i.e. the returned myPlot contains methods, plotstate, and history, but it’s current plotstate is always overwritten, and old state is pushed onto a history list)
  • es6 - it’s definitely mature enough, and there’s a lot of niceties that we could take advantage of
  • agreed upon standard lib/prelude

edit: April 14

  • logging utils that can be set to either verbose or silent (part of our prelude perhaps). Done

edit: April 22

  • slimmed down interface. We could likely reduce the method count to 3-5, namely a constructor Plotly.plot, and instance methods Plot.update, Plot.export and maybe a few others that don’t fit as an update.

edit: April 26

  • tooling to verify public interfaces meet standards, e.g. checking that all attribute names are snake_case or camelCase (depending on what we choose)

edit: May 3rd

  • all positioning in normalized units (margins specifically)

I would love to see autosizing fixed so that it works in flexbox or any dynamically sized containers. If a container’s width/height is auto the plot size always defaults to 700x450px. This then requires the use of resize events and Plots.resize() to get things to behave. It would be nice to refactor the svg plotting to just be sized to 100% of the container instead of using explicit pixels values.

Revamp our set of default colorscales.

Besides agreeing with the above two lists, based on very limited work, take it with huge grain of salt:

  1. D3 might be used in some places; e.g. category scales/axes could be done via the ordinal scale even if mapping is made to logical points (e.g. the index of the axis tick); sometimes two D3 scales are linked (range of one is domain of the other). Might not work out but D3 scales are pretty powerful, especially in the upcoming D3 4.0.
  2. Smaller, and to the extent possible, pure functions, immutability as the default.
  3. (long term) Thinking about reactive visualization, e.g. streaming in new data points into a plot; it would smoothly transition to a possibly enlarged x/y domain; similar behavior with controls. Maybe it’s mostly covered, I haven’t seen enough. The reason for mentioning it is, it chimes with pure functions and immutability in that it’s easier to base dynamic behavior atop of less imperative code.
  4. lodash/fp to replace typical, repeating code patterns, it’s a painstakingly optimized library, it isn’t just using slow [].map etc.
  5. I saw that some Jasmine test require PlotlyInternal (rather than Plotly); maybe worth using the public API for all tests, but again, maybe PlotlyInternal is much like an API except some of it is not (yet) user-exposed.
  • Remove ALL auto* attributes: if a value is needed and not provided, that’s enough to indicate that it should be determined automatically, just like all other defaults. This might be too broad a statement, but I think it’s mostly the right goal. There are a few bits of functionality we will need to find a new home for, like autorange: 'reversed'
  • And related to this but perhaps not exactly congruent, NO mutations to gd.data or gd.layout during Plotly.plot. This requirement has been hinted at elsewhere in this issue but I don’t think it was explicitly stated.

#3044 may serve as a model for this kind of behavior, using _private attributes to stash values determined during calc rather than supplyDefaults

Add TypeScript definitions types with every new Plotly.js release and link to NPM @types repo https://www.npmjs.com/package/@types/plotly.js

  • drop the undo/redo queues that we have built into restyle and relayout and our other API methods - we used these in our old workspace, but this is really not the right level to be managing this issue, as plots may be coupled to other application state (ie changes in data arrays) and using our queue would muck up that correspondence.
  • Please allow callbacks for labels, text, values etc, so that their number can be specified and a callback provided to retrieve values, labels, text, hover text etc by index (passed to callback as a parameter).
  • Let us build hover text with a callback by index, and allow any HTML in the hover text

Any plans to support react-native? I found a third party dev who build this: https://github.com/rynobax/react-native-plotly any thoughts?

To add to the ancient discussion about axis names. Subplot naming for non-cartesian could be made more consistent. I.e. have scene and geo renamed to subplot like the rest. Perhaps gl3d to scene.

  • Change the default layout.hovermode from 'x' (compare) to 'closest'. In #778 we discussed setting restrictions on when cartesian plots could default to compare mode (we already separate out non-cartesian and horizontal traces here) but this is both difficult to do (requires digging into data arrays during supplyDefaults) and potentially error-prone, and can still be a source of confusion (see clickmode #1852, spikelines). Seems better just to default to 'closest' and make compare modes explicitly opt-in.

Continuing from @etpinard comment https://github.com/plotly/plotly.js/issues/420#issuecomment-364454752

Instead of deprecating Plotly.plot rename Plotly.react to Plotly.plot. react may be a somewhat unfortunate name for a method that has the “whole plot specification” of Plotly.plot and the performance of Plotly.update. Also it is highly useful for those using JQuery, Angular, Vue etc.

  • make parcoords tick label format default to the same as cartesian axes, rather than a fixed tickformat - see #2468

Suggestion: now that Plotly.react got implemented in https://github.com/plotly/plotly.js/pull/2341, perhaps we start thinking about removing 🔪 Plotly.plot, Plotly.redraw, Plotly.restyle, Plotly.relayout, Plotly.update and Plotly.moveTraces entirely from the library make Plotly.react the only official way to update an existing plotly graph? The restyle call signature has always been hard to grasp for new plotly.js users. As Plotly.react has the small call signature as Plotly.newPlot, this should be an improvement.

We could probably remove Plotly.extendTraces and Plotly.preprendTraces at some point too, but it might best to keep them and turn them into fast(er) 🐎 routine optimize for streaming data.

Just a thought. Maybe some users really like Plotly.restyle and Plotly.relayout

  • remove the plotly_selected event with undefined data that gets emitted when clicking on the plot area in a select mode - see #2241
  • more visible and well-documented way to set logging level (than Plotly.setPlotConfig) - @etpinard suggests a top-level method for it like Plotly.setLogLevel
  • drop the strange functionality relayout(gd, {'xaxis.reverse': true}) and change the handling of axis.autorange: 'reversed' from a weird disappearing setting to regular behavior where autorange: true always results in an increasing range and autorange: 'reversed' is always reversed. Would also require the doubleclick interactions to choose whether to set autorange to true or 'reversed' in order to behave the way they do today, but editing behavior would be more intuitive.

is there no desire to support plots which specify time as epoch nanoseconds?

The precision we have right now - 100 microseconds, one digit better than native dates support - is the best I found I was able to reliably handle using a single javascript number to specify the coordinate. I could imagine a system supporting arbitrary precision within a restricted range where the zero point of the axis linearization is allowed to float - this would be a fairly big project but could be done if someone was sufficiently interested in sponsoring it 😉

Note that this wouldn’t imply any backward incompatibility, so need not be associated with v2

I’d vote for the opposite. Rename all axis ids 'xaxis', 'xaxis2', 'yaxis2', …

That could work. It gives us the same simplification, clears up the ambiguity, and is a smaller change for users to adapt to. Means we have to do something more clever to manage backward compatibility but maybe that’s unavoidable.

I’d vote for not having “names” that require parsing at all - put them as indexed elements in a list.

Like layout.xaxes=[{...}, {...}, {...}]? two things bother me with that idea:

  • If you delete an axis, all your references to later axes need to change
  • It violates the idea of “simple things should be simple” - almost all plots have only one x axis, and making everyone put that axis into a list just because some other people will make multiple axes is annoying. And then scenes, ternaries, geos that can only have one axis of each type, either the structure is different or they also have that extra list cruft.

I’d vote for not having “names” that require parsing at all - put them as indexed elements in a list.

  • Specify log axes with data values, not linearized values. ie range [0.1, 100] rather than [-1, 2]. For dates we’re doing this in #1078 but I can’t see a backward-compatible way to do it for logs. This also applies to annotation and image positions (but shapes already get it right!) and tick0. Perhaps in 2.0 we also remove the compatibility transform that #1078 introduces for dates that supports the old range-as-epoch-milliseconds format.
  • Along the lines of “Drop ‘add’ and ‘remove’ relayout values” above, drop the built-in coordinate transforms when an annotation or shape has its axis references changed. This is really just for GUI editing so should reside in streambed.

Maybe we should drop Plotly.redraw in v2.0.0 ?

⬆️ there is palette overlap between plotly.js and some of its webgl renderers, with a different resolution. Slight restructuring would make room for one shared palette set definition at a finer than current resolution.

Add OO API e.g :

This seems like a good place to discuss smooth transitions as well (requested in #142, and experimented with in https://github.com/ropensci/plotly/pull/547). It’d be awesome if plot worked like a d3 selection wrt transitions:

plot
  .transition({duration: 100, ease: 'cubic'})
  .restyle('marker.color', 'red')

Also, in my mind, transitioning positions (x/y) is the most important use case, so it’d be super useful if restyle() (or some other method) could also support this:

plot
  .transition({duration: 100, ease: 'linear'})
  .restyle('scatter', {x: [1, 2], y: [1, 2]})

There are multiple ways to transition a path, but I think I’d almost always want to transition the transform.