I'm having problems with touch screen overscrolling on Chrome.
I have a document with am SVG element in it, which contains some shape, say a rectangle:
Now, I want to make the rectangle draggable, which means that I want to disable all kinds of touch actions on the respective <rect>
element, by setting it's style property touch-action: none
.
This works fine on all desktop browsers, except Chrome. On Chrome, when I touch and move on a rectangle, browser's overscroll feature kicks in. This causes the browser window to awkwardly move, as well as all Pointer events that I have set on the rectangle cancelled.
I.e. pointermove
is registered for a fraction of second, then it just stops when overscroll kicks in. pointerup
is never called even when touch is released.
Now, if I had an HTML element instead of an SVG element, setting touch-action: none
would do the job. The same thing on an SVG element fails.
Technically, this could be solved by either setting touch-action: none
on document.body
or wrapping the whole SVG into a <div>
element with touch-action: none
set.
Unfortunately, that is not an option for me since I need the document (and rest of the rectangle-surrounding SVG) to retain all of its original touch gestures, except when directly on a rectangle.
As a solution, I did try to dynamically set touch-action: none
on document: body
when pointerdown
event occurs on a rectangle.
// Get element
var o = document.getElementById( "test" );
// disable touch action on press of the SVG element
o.addEventListener( "pointerdown", function(e) {
document.body.style.touchAction = "none";
} );
// re-enable touch action when released
o.addEventListener( "pointerup", function(e) {
document.body.style.touchAction = "auto";
} );
Unfortunately, that does not help. The style on body gets set and next time I try dragging rectangle it works as expected (because pointerup
event never gets executed), just not this time.
Adding preventDefault()
to event handlers has also no effect.
I would appreciate if someone who have had similar experience could share a solution.
Here's a live example of the above.
// Get element
var o = document.getElementById( "test" );
// disable touch action on press of the SVG element
o.addEventListener( "pointerdown", function(e) {
document.body.style.touchAction = "none";
} );
// re-enable touch action when released
o.addEventListener( "pointerup", function(e) {
document.body.style.touchAction = "auto";
} );
<svg id="test" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width: 300px; height: 300px; border: 1px solid #eee;">
<g transform="translate(50,50)">
<rect fill="#00fff0" width="200" height="200" style="touch-action: none;"></rect>
</g>
</svg>
UPDATE: looks like using preventDefault()
on an touchstart
event does the trick.
However, it seems to be wrong to use both modern pointerdown
and legacy touchstart
at the same time. This seems like a bug in Chrome 60. If anyone could confirm it, that would be great.
I think it would be enough by preventing touchstart
:
window.addEventListener( "touchstart", function(e) {
// Determine wether or not you are panning from rectangle:
if (e.target ....)
e.preventDefault();
} );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With