d3 / d3-zoom

Pan and zoom SVG, HTML or Canvas using mouse or touch input.
https://d3js.org/d3-zoom
ISC License
505 stars 143 forks source link

Zoom behaviour with retina canvas #133

Closed interwebjill closed 5 years ago

interwebjill commented 6 years ago

Comparing the Canvas Semantic Zooming example: https://bl.ocks.org/mbostock/3681006 with an example adjusted for retina screens: https://bl.ocks.org/interwebjill/d7c22e37e7c05ad6018ee62481316737/e0916413c0544dc1251597d0dbb2834cf92c8596

you can see that the zoom center is off. This scale difference creates other problems as well, particularly when using .scaleTime():

https://bl.ocks.org/interwebjill/206425109aa902c2928fa22b8a9f5fd8

mbostock commented 6 years ago

The zoom behavior uses d3.clientPoint to get the location of the pointer, and this function only supports transforms on SVG elements because they implement element.getScreenCTM. HTML elements may support similar functionality in the future if the GeometryUtils specification is implemented by browsers; this provides element.convertPointFromNode. Unfortunately, it’s not easy to polyfill the GeometryUtils specification, and I have no plans to do so in D3.

D3 3- supported zoom.center (see example) which would allow you to control the center manually, which might provide a workaround for this problem. You can achieve similar functionality in D3 4+ using programmatic zooming, but I’m not sure I have an existing example.

interwebjill commented 6 years ago

I can capture the zoom event with an overlapping svg rectangle. The only adjustment that needs to be made is to reset the zoom center of the canvas to half that of the rectangle.

https://bl.ocks.org/interwebjill/cc5361ca1d1c5538fab19999785c6d01

mbostock commented 6 years ago

Yes, using a non-transformed overlay to bind the zoom behavior would be a reasonable workaround.

interwebjill commented 6 years ago

Here is the solution:

https://bl.ocks.org/interwebjill/cc5361ca1d1c5538fab19999785c6d01/008a48fb08c743ed1d443a414ecec7485570bbd0

mbostock commented 5 years ago

Closing to inactivity.