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

Default zoom.touchable should use navigator.maxTouchPoints, if supported? #162

Closed lojjic closed 5 years ago

lojjic commented 5 years ago

As of Chrome 70, d3-zoom no longer works out of the box when using touch on desktop touchscreens. This is because Chrome has removed the ontouch* element properties on desktop OSes, and d3-zoom's defaultTouchable implementation relies on the presence of the ontouchstart element property as its feature detection. It therefore thinks touch events are unsupported, even though they still are.

See https://www.chromestatus.com/feature/4764225348042752 for their explanation.

We can work around this on a case-by-case basis by overriding the touchable config with our own implementation via zoom().touchable(...), but it would be nice to have a more reliable feature detection in defaultTouchable. It sounds like checking for the presence of window.TouchEvent should work ok but it would need proper cross-browser testing.

Alternative solutions might be: removing the filter altogether and just letting it attach unused touch event handlers in all cases, or adding a PointerEvents-based code path since that's apparently the recommended long-term approach.

mbostock commented 5 years ago

See also https://github.com/d3/d3-drag/issues/47#issuecomment-437504346.

mbostock commented 5 years ago

We can’t remove the filter; that was added in 34c2657e2c4ae2a75c3e16ce23a79e064b63602f to avoid a [Violation] warning in Chrome.

I considered switching to pointer events, but it still isn’t supported in Safari, so it doesn’t seem ready. (Plus, I imagine it’ll be a pain to rewrite in terms of pointer events, and an even bigger pain to try to support mouse and touch in addition to pointer events.)

I think using navigator.maxTouchPoints > 0 as the default touchable implementation sounds good, though. Never mind, that’s also not supported in Safari.

mbostock commented 5 years ago

We could still use navigator.maxTouchPoints if not undefined, though.