leeoniya / uPlot

📈 A small, fast chart for time series, lines, areas, ohlc & bars
MIT License
8.78k stars 386 forks source link

mouseMove and CSS transforms don't get along #734

Open tve opened 2 years ago

tve commented 2 years ago

I have uPlots embedded in pages where I'm using a CSS transform to scale the entire page up or down. This mostly works, but the mouse position is not tracked correctly. Someone else hit the same problem and created a codepen: https://codepen.io/chrisdalke/pen/WNomELr look at the third chart and how the crosshair position is out of sync with the mouse pointer. Basically, uPlot uses page pixels but the whole uPlot is scaled by 2x so the cross hairs diverge from the pointer as you move right and down from the top-left corner. MouseMove should use "element coordinates" that are scaled by the browser just like the element is scaled.

(I have no association with the user that created that codepen, I just bumped into it as I was going to create my own codepen, saved me a bunch of work :-).

I played around a bit and the following fixes the issue for me. In cacheMouse https://github.com/leeoniya/uPlot/blob/master/src/uPlot.js#L2737-L2740 replace by:

        if (e != null) {
            _l = e.offsetX;
            _t = e.offsetY;
        }

I'm not a browser event whizz so I don't know what else this might break. The mozilla docs https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX are "clear as mud" to me...

Thanks for an amazing lib overall!!!

leeoniya commented 2 years ago

wow, that's super embarrassing on my part to have spent multiple commits on trying to keep this in sync with minimal perf impact. check out how much code gets dropped with your suggested change in the linked commit :tada:

thanks!

tve commented 2 years ago

yikes! I'm happy I stumbled into this by chance :-)

leeoniya commented 2 years ago

reverted this due to #750, we'll need another strategy.

looking at the codepen you linked, scaling with CSS transforms is actually pretty crappy. you lose a bunch of resolution in the canvas, various other things will probably break, like the line pathBuilders which rely on devicePixelRatio to infer a specific pixel density, etc. i'm not sure this is something that should be encouraged/supported; even if we figure out the mouse issue, there will be additional issues that will be more difficult or impossible to solve. using CSS transforms with raster images and canvas is not as nice as with svg and dom-rendered elements and text.

tve commented 1 year ago

looking at the codepen you linked, scaling with CSS transforms is actually pretty crappy.

Yes & no. It's crappy if you scale by a lot, it's fine, especially on HiDPI devices if you scale by up to 25% or so. I use it to scale pages on iPads in particular where scaling all the elements individually changes the layout in undesired ways.

tve commented 1 year ago

FYI, I backed out the use of the transform in my use-case. Still bummed about this, though. Feel free to close if you're not going to pursue this further.