Plotly.js: image and heatmap traces jump/flash on Firefox and Safari

Created on 21 Nov 2019  Â·  16Comments  Â·  Source: plotly/plotly.js

The new image trace seems to have a flashing/jumping behavior when zoomed in and panning on Firefox and Safari. (Firefox version 69.0, Safari version 13.0.3)

Example from https://plot.ly/python/imshow/

image_jump

This jumping does not happen on Chrome but I do see it on Firefox/Safari. Not sure if it's related, but in all three browsers, the tooltip also seems to jump to another location when the pan is completed.

bug ♥ NEEDS SPON$OR

Most helpful comment

So we're reverting the drag, then redrawing with the new view... and it seems like even if we do this synchronously, some browsers will do two repaints (if that's it, there will be async edge cases in other browsers too). I wonder if we can just not revert the drag, and tweak the redraw process if necessary so it still works right. I think it's this call that's doing it:

https://github.com/plotly/plotly.js/blob/4ab3b49c12e3e8be3800f7e4aacd4dddcf497357/src/plots/cartesian/dragbox.js#L770-L774

updateSubplots seems to modify some internal state as well as adjusting viewboxes, we still may need the internal state even if we don't change anything visible.

All 16 comments

@jonmmease I think the issue also occurs on heatmap (https://plot.ly/python/heatmap/). Could you rename the issue to reflect that?

The problem stems from reinjecting an image when pan operation is completed. I thought this pattern was safe since it's been used for a long time in heatmap. Maybe this issue only affects newer versions of Firefox :thinking: ?

Could you rename the issue to reflect that?

Done, thanks!

Hmm. I can't replicate in FF 70

Hmm, I am seeing it in FF 70 on Ubuntu. @antoinerg were you able to reproduce?

Hmm, I am seeing it in FF 70 on Ubuntu. @antoinerg were you able to reproduce?

I can reproduce it in FF 70.0.1 (64-bit) on Linux (NixOS distro).

I can also reproduce in Safari 13.0.3 on macOS 10.15.1.

On the same system, the problem does not appear in Chrome Version 78.0.3904.108.

@antoinerg do you think there's an "easy" way to fix this bug?

Or do you think our canvas -> pixels -> img inside the _paper SVG is fundamentally flawed and FF does behaves as expected?

Or do you think our canvas -> pixels -> img inside the _paper SVG is fundamentally flawed and FF does behaves as expected?

It's hard to say which one behaves right and I suspect the specification may not be clear in this regard.

do you think there's an "easy" way to fix this bug?

Idea for an easy fix: have two images (A and B) and alternate between the two. Once you pan, image B content is updated and moved in front of image A (so no flash in principle). Then if you pan again, image A content is updated and moved in front and so on. Hopefully, this approach works.

If we only target a fix for FF: leverage image-rendering: pixelated, draw the image only once and things will fly :racehorse:.

So we're reverting the drag, then redrawing with the new view... and it seems like even if we do this synchronously, some browsers will do two repaints (if that's it, there will be async edge cases in other browsers too). I wonder if we can just not revert the drag, and tweak the redraw process if necessary so it still works right. I think it's this call that's doing it:

https://github.com/plotly/plotly.js/blob/4ab3b49c12e3e8be3800f7e4aacd4dddcf497357/src/plots/cartesian/dragbox.js#L770-L774

updateSubplots seems to modify some internal state as well as adjusting viewboxes, we still may need the internal state even if we don't change anything visible.

FYI: using some navigator.userAgent-based solution here would be :ok_hand: with me.


It would be interesting to see how image-rendering: pixelated performs in comparison to the current algorithm. Using that in browsers that support it could be a big win and allow us to fix this problem in FF.

The solution in https://stackoverflow.com/questions/14704796/image-reload-causes-flicker-only-in-firefox/14711272#14711272 may be a quick and easy way to fix this bug in Safari (albeit with a potential performance cost).

The issue is twofold:

  1. Image is flashing (can be fixed by not redrawing the image)
  2. Tooltip appears at the position of the last click

EDIT: I opened an issue to tackle 2) since it affects other trace types (https://github.com/plotly/plotly.js/issues/4570)

@etpinard at the moment, when an axis has a scaleanchor attribute (the default for image), the calc step is called on every pan operation. For the planned improvement to the image trace type, this is somewhat undesirable. We'd like to produce the image in calc once and then simply move/scale it in the plot phase when a pan operation is completed. The goal is to save ourselves from the sometimes expensive operation of looping over all the pixels in view (and then some). Do you see potential roadblocks or flaws in trying to achieve what I just described? How would you go about skipping the calc phase when it's being triggered by a pan?

Here's the relevant logic that makes zoom interactions go through the 'calc' pipeline:

https://github.com/plotly/plotly.js/blob/15d75db46fb88d5dd11b8d6945bb74064198c47e/src/plot_api/plot_api.js#L2274-L2293

By the looks of it, all the range "constraints" operations are taken care of in

https://github.com/plotly/plotly.js/blob/15d75db46fb88d5dd11b8d6945bb74064198c47e/src/plots/cartesian/constraints.js#L198-L352

which is called during

https://github.com/plotly/plotly.js/blob/15d75db46fb88d5dd11b8d6945bb74064198c47e/src/plot_api/subroutines.js#L669-L721

from a few places in plot_api.js including in the "fast" 'axrange' edit pipeline:

https://github.com/plotly/plotly.js/blob/15d75db46fb88d5dd11b8d6945bb74064198c47e/src/plot_api/plot_api.js#L1970-L1976


So perhaps zoom/pan interaction _just work_ already under the fast 'axrange' edit pipeline? @antoinerg have you tried commenting the above block in _relayout to see in any tests fail?

We'll have to be extra careful though. I wouldn't want to trust 100% our test coverage for constraints.

But yeah, to answer your question, making zoom/pan on constrained axes not have to go through the 'calc' pipeline would be a huge win for image traces. Maybe 'axrange' works already, maybe we'll need a new flavour of that 'axrange' pipeline, but yeah we can do better than 'calc'!

(Ping, I updated my comment above)

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

Sponsorship range: $10k-$15k

What Sponsorship includes:

  • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
  • Tests for this feature
  • Long-term support (continued support of this feature in the latest version of Plotly.js)
  • Documentation at plotly.com/javascript
  • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
  • Possibility of integrating this feature with Dash
  • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
  • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

Please include the link to this issue when contacting us to discuss.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danielsamuels picture danielsamuels  Â·  3Comments

HunterMcGushion picture HunterMcGushion  Â·  3Comments

bryaan picture bryaan  Â·  3Comments

chriddyp picture chriddyp  Â·  3Comments

boleslawmaliszewski picture boleslawmaliszewski  Â·  3Comments