You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug: interactions misaligned when plot is inside transform: scale()-ed element #888
Looks like plotly.js miscalculates where the mouse is positioned if the plot itself is rendered inside an element with a transform: scale() CSS property set. The tooltips don't match up with where the mouse is. This is most apparent when you try to click+drag an area of the plot and it clearly shows the locations don't match up.
The buttons in the toolbar line up correctly, as does the hitbox for dragging the axes or enabling/disabling specific traces.
Also it looks like if you're at the top-left corner of the plot, the mouse position is accurate (that is, the (0, 0) origin point is handled correctly; only the scaling factor is off).
Implementation notes from when I rediscovered this issue just now:
If the page transforms the plotDiv element (or any parent of it) with a scale, rotation, or matrix, any call to getBoundingClientRect on an element within that div gives us misleading results and breaks hover effects. Certain getBoundingClientRect calls are necessary to find text sizing, but this should always be called on elements in gd._tester, which we attach directly to <body>, far off-screen. We should get rid of all other getBoundingClientRect calls. This will also be better for performance.
Seems from the comments here like the problems extend beyond just getBoundingClientRect calls though - I guess anything that depends on clientX and clientY from the mouseEvent is susceptible. In principle I guess we'll need to find a way to invert the transform in order to interpret these correctly... make 3 little test elements in different corners of the plot and call getBoundingClientRect on each? window.getComputedStyle().transform on the plot and all its parent nodes and combine them? Those all sound kind of painful, any other options I'm not thinking of?
Related I suspect: doesn't seem to be an issue in Chrome, but in FF if I move a plot from my external monitor to my laptop monitor (retina display, 2x resolution but this seems partially masked) hover labels get messed up:
And retina -> normal:
@alexcjohnson yes, moving between screens with a different devicePixelRatio would need that everything that depends on it be rerendered. On an old project I used polling (a few times a second with a setInterval), now one can create an event listener on a media query:
I'm having this problem too. My app requires zooming entire charts, and because of this bug I have to make duplicate enlarged versions of every chart, and swap them out every time the user zooms.
On a side note: notice that I'm implementing click-to-zoom using pure HTML+CSS. This is because I can't get a click event in the main plot area to work because of the transparent div overlays. Here are my semi-failed attempts at doing it in Javascript: https://codepen.io/anon/pen/RLzWMr https://codepen.io/anon/pen/wrLxJW
The transform: scale() still does not work, neither on FF 52 nor Chrome 64.
I am using plotly.js to draw graphs in my presentations (using https://github.com/gnab/remark), and the presentation framework uses transform: scale() to scale the slide, which breaks plotly interactions.
I think this is the same problem I have with plotly plots embedded in reveal.js slides which get scaled to fit the window size. If reveal.js is forced to scale=1 then hover and mouse coordinates behave correctly, but this is not a solution because then slides do not fill the screen :)
I faced the same issue with reveal.js. My workaround is to add a CSS transform which precisely undoes Reveal's scaling and then scale the plot with its width and height attributes. Something along the lines of
we'll need to find a way to invert the transform in order to interpret these correctly... make 3 little test elements in different corners of the plot and call getBoundingClientRect on each? window.getComputedStyle().transform on the plot and all its parent nodes and combine them? Those all sound kind of painful, any other options I'm not thinking of?
@alexcjohnson, how about putting the responsibility for detecting the transform on the user? Maybe the layout object could have an optional property called parenttransform or something that points to a callback function that returns the transformation matrix or a string of individual CSS transforms. Then hover or other interactions could just invert the transformation to calculate the correct position. I know this isn't ideal, but it's a simple fix that would provide a useful workaround for many users still suffering from this bug.
Due to a specific requirement of fitting multiple charts which are added dynamically and arranged horizontally in available viewport without scroll I am using transform scale for example transform: translateZ(0) scale(0.50, 0.50) on charts based on available space, although the whole chart is scaled down uniformly but when mouse hover over is done on chart I observe there is offset between mouse location and hover popup location shown in attached screen shot
Using resize() or relayout does not give crisp chats when they are scale down due to uneven transform of chart and labels.
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)
I have a fix working for the hover aspect of this bug. It is similar to Palantir's plottable fix mentioned above, in that it traverses the DOM ancestors of the event target element to produce a transform matrix, then applies the inverse of that to a point. However, there are multiple mouse interactions affected by this issue (such as clicking and dragging, hover, and probably others I can't think of or don't know about), and the fix applied to the hover case is a bit specific.
To be precise - it transforms xpx and ypx in the components/fx/hover.js _hover() call thus:
I would like guidance on what a fix PR for this should look like - is it going to have to be a fix for every interaction in the same vein as the hover code above, or is there a more general way of doing things, e.g. transforming further up the chain? I've tried doing that, with little success - I think my lack of knowledge of the codebase is limiting me.
Another workaround solution for this problem is to change main charting library from Plotly to mpld3. Of course, is not ideal and depends highly on your use case, but solves the initial problem ;). You can find more info on the issue, as well as some example code in my sample repository.
This issue was tagged as "needs sponsorship" and was instead resolved by the contribution of an excellent pull request for this long-standing issue. Thank you so much for taking the initiative on this @alexhartstone!
Misalignment is happening for me in Chrome 92.0.4515.159 (Plotly.py 5.2.2, Jupyter Lab 3.0.16) but not in Firefox 91.0.2. Found the same behavior in both OSX and Linux, i.e., works in FF but not Chrome-based browsers.
Slides were created with jupyter nbconvert --to slides --no-input --no-prompt
I also saw the misalignment in tooltips in plots created by altair and mpld3.
This is still happening on Chrome and Microsoft Edge. Unfortunately, I can't install FireFox on my computer. Your help fixing this bug or at least providing a workaround would be greatly appreciated.
Activity
etpinard commentedon Sep 1, 2016
Ah. I guess you must be the first person to use plotly.js with CSS transforms.
Thanks for reporting.
MaximilianBuegler commentedon Mar 7, 2017
I'm having the same issue. Any news on this?
everly commentedon Mar 9, 2017
This is also preventing click events from firing properly
alexcjohnson commentedon May 10, 2017
Implementation notes from when I rediscovered this issue just now:
If the page transforms the
plotDivelement (or any parent of it) with a scale, rotation, or matrix, any call togetBoundingClientRecton an element within that div gives us misleading results and breaks hover effects. CertaingetBoundingClientRectcalls are necessary to find text sizing, but this should always be called on elements ingd._tester, which we attach directly to<body>, far off-screen. We should get rid of all othergetBoundingClientRectcalls. This will also be better for performance.Seems from the comments here like the problems extend beyond just
getBoundingClientRectcalls though - I guess anything that depends onclientXandclientYfrom themouseEventis susceptible. In principle I guess we'll need to find a way to invert the transform in order to interpret these correctly... make 3 little test elements in different corners of the plot and callgetBoundingClientRecton each?window.getComputedStyle().transformon the plot and all its parent nodes and combine them? Those all sound kind of painful, any other options I'm not thinking of?alexcjohnson commentedon May 18, 2017
Related I suspect: doesn't seem to be an issue in Chrome, but in FF if I move a plot from my external monitor to my laptop monitor (retina display, 2x resolution but this seems partially masked) hover labels get messed up:


And retina -> normal:
monfera commentedon Sep 21, 2017
@alexcjohnson yes, moving between screens with a different
devicePixelRatiowould need that everything that depends on it be rerendered. On an old project I used polling (a few times a second with asetInterval), now one can create an event listener on a media query:...hm this works on Chrome on FF but not (yet?) on Safari. So, polling might be safer atm.
nicknack23 commentedon Oct 24, 2017
I'm having this problem too. My app requires zooming entire charts, and because of this bug I have to make duplicate enlarged versions of every chart, and swap them out every time the user zooms.
Here is a codepen that demonstrates my use case.
On a side note: notice that I'm implementing click-to-zoom using pure HTML+CSS. This is because I can't get a click event in the main plot area to work because of the transparent div overlays. Here are my semi-failed attempts at doing it in Javascript:
https://codepen.io/anon/pen/RLzWMr
https://codepen.io/anon/pen/wrLxJW
foxik commentedon Feb 25, 2018
The
transform: scale()still does not work, neither on FF 52 nor Chrome 64.I am using
plotly.jsto draw graphs in my presentations (using https://github.com/gnab/remark), and the presentation framework usestransform: scale()to scale the slide, which breaks plotly interactions.Any idea how this could be fixed?
alexeid commentedon Mar 27, 2018
I think this is the same problem I have with plotly plots embedded in reveal.js slides which get scaled to fit the window size. If reveal.js is forced to scale=1 then hover and mouse coordinates behave correctly, but this is not a solution because then slides do not fill the screen :)
fruchti commentedon Mar 27, 2018
I faced the same issue with reveal.js. My workaround is to add a CSS transform which precisely undoes Reveal's scaling and then scale the plot with its width and height attributes. Something along the lines of
I added the
data-target-attributes so I could do this. There are probably more elegant ways but it does the job. I hope it helps someone!EDIT: I just noticed this workaround doesn't seem to work in Chrome, only in Firefox.
nicknack23 commentedon Sep 2, 2018
@alexcjohnson, how about putting the responsibility for detecting the transform on the user? Maybe the
layoutobject could have an optional property calledparenttransformor something that points to a callback function that returns the transformation matrix or a string of individual CSS transforms. Then hover or other interactions could just invert the transformation to calculate the correct position. I know this isn't ideal, but it's a simple fix that would provide a useful workaround for many users still suffering from this bug.hellochar commentedon Sep 13, 2018
FYI Plottable's fixed this here: https://github.com/palantir/plottable/blob/b6e36fbd4d8d7cba579d853b9f35cc260d1243bf/src/utils/mathUtils.ts#L173 . The gist is to walk up the DOM tree and account for the
transformproperties of each elementetpinard commentedon Nov 19, 2019
Another report from #4343
Due to a specific requirement of fitting multiple charts which are added dynamically and arranged horizontally in available viewport without scroll I am using transform scale for example transform: translateZ(0) scale(0.50, 0.50) on charts based on available space, although the whole chart is scaled down uniformly but when mouse hover over is done on chart I observe there is offset between mouse location and hover popup location shown in attached screen shot
Using resize() or relayout does not give crisp chats when they are scale down due to uneven transform of chart and labels.
I have created code pen to explain issue
https://codepen.io/contactsandygo/pen/wvvXdov
jackparmer commentedon Sep 10, 2020
This issue has been tagged with
NEEDS SPON$ORA 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:
Please include the link to this issue when contacting us to discuss.
alexhartstone commentedon Sep 29, 2020
I have a fix working for the hover aspect of this bug. It is similar to Palantir's plottable fix mentioned above, in that it traverses the DOM ancestors of the event target element to produce a transform matrix, then applies the inverse of that to a point. However, there are multiple mouse interactions affected by this issue (such as clicking and dragging, hover, and probably others I can't think of or don't know about), and the fix applied to the hover case is a bit specific.
To be precise - it transforms xpx and ypx in the components/fx/hover.js _hover() call thus:
I would like guidance on what a fix PR for this should look like - is it going to have to be a fix for every interaction in the same vein as the hover code above, or is there a more general way of doing things, e.g. transforming further up the chain? I've tried doing that, with little success - I think my lack of knowledge of the codebase is limiting me.
zawalich commentedon Oct 19, 2020
Another workaround solution for this problem is to change main charting library from Plotly to mpld3. Of course, is not ideal and depends highly on your use case, but solves the initial problem ;). You can find more info on the issue, as well as some example code in my sample repository.
archmoj commentedon Oct 22, 2020
#5193 with some adjustments is getting close to address this issue.
nicolaskruchten commentedon Nov 19, 2020
This issue was tagged as "needs sponsorship" and was instead resolved by the contribution of an excellent pull request for this long-standing issue. Thank you so much for taking the initiative on this @alexhartstone!
davidlove commentedon Aug 27, 2021
Misalignment is happening for me in Chrome 92.0.4515.159 (Plotly.py 5.2.2, Jupyter Lab 3.0.16) but not in Firefox 91.0.2. Found the same behavior in both OSX and Linux, i.e., works in FF but not Chrome-based browsers.
Slides were created with
jupyter nbconvert --to slides --no-input --no-promptI also saw the misalignment in tooltips in plots created by altair and mpld3.
jzadra commentedon Oct 14, 2022
This is still happening for me with Chrome. Working correctly in Firefox.
Moving-Electrons commentedon Nov 28, 2022
This is still happening on Chrome and Microsoft Edge. Unfortunately, I can't install FireFox on my computer. Your help fixing this bug or at least providing a workaround would be greatly appreciated.
jknottUOW commentedon Jun 29, 2023
This is also unfortunately still happening for me too on Chrome. It does work as expected on Firefox, across a wide range of wondow sizes.