This problem (bug?) is driving me crazy. I can't find any existing issues on it, but maybe I'm missing something. I hope there is some solution, workaround or bug fix.
In web browsers on Android, panning breaks for elements inside an <svg> tag. The same problem does not arise when given a <div> the same treatment.
It's nicely shown by this CodeSandBox example, which you obviously have to run in an Android web browser to see it break.
Here is a video showing the issue on a Nexus 5X.
Description of what's happening:
<svg> tag (e.g. a <circle>).panstart fires correctly.panmove will also trigger correctly.panmove will stop firingpanend will no longer fire (it _will_ if you didn't drag too far)I tested both on an up-to-date Chrome app and a default browser on an old Android. Same effect.
UPDATE 15 June 2018:
See this thread: it seems someone else is experiencing the same problem and dug deeper than I did. He found out that the pancancel is being triggered, because a pointercancel is being thrown by the browser. Still not clear why this is happening and how to deal with this.
By digging deeper into the pancancel and pointercancel, I found a workaround that works fine for me (but your mileage may vary):
For Android browsers, It turns out that preventing the default "touchmove" event handling on the window will solve this problem for any SVG element on the page, as it will prevent the browser from noticing the touch event and assuming the user is scrolling (which triggers the pointercancel, which triggers the pancancel). That's great news, but it also disables all scrolling behaviour on the page. What I've done instead is catching the "touchmove" event on the SVG object, so any descendants in it will pan properly. I'm not yet sure if it has any bad side effects, but so far it has meant that my panning in SVG finally works on Android browsers!
Here's the straightforward code I used, though notice the need for the specific option:
const options = { passive: false }; // needed because Chrome has this set to "true" by default for "touchmove" events
mySVG.addEventListener(
"touchmove",
e => e.preventDefault(),
options
);
I will keep this issue listed here, because I think it's something that should be handled (i.e. abstracted away) by HammerJS. For now, I hope people with a similar problem will find this and need less time debugging this one.
By digging deeper into the
pancancelandpointercancel, I found a workaround that works fine for me (but your mileage may vary):For Android browsers, It turns out that preventing the default "touchmove" event handling on the window will solve this problem for any SVG element on the page, as it will prevent the browser from noticing the touch event and assuming the user is scrolling (which triggers the
pointercancel, which triggers thepancancel). That's great news, but it also disables all scrolling behaviour on the page. What I've done instead is catching the "touchmove" event on the SVG object, so any descendants in it will pan properly. I'm not yet sure if it has any bad side effects, but so far it has meant that my panning in SVG finally works on Android browsers!Here's the straightforward code I used, though notice the need for the specific option:
const options = { passive: false }; // needed because Chrome has this set to "true" by default for "touchmove" events mySVG.addEventListener( "touchmove", e => e.preventDefault(), options );I will keep this issue listed here, because I think it's something that should be handled (i.e. abstracted away) by HammerJS. For now, I hope people with a similar problem will find this and need less time debugging this one.
It works and thanks a lot!
Very help full me, thanks!
This problem can reproducing also by PC GoogleChrome(75.0.3770.100) Toggle device toolbar(Ctrl+Shift+M).
いろいろテストしていたところ、e.preventDefault()をかけた場合、二回目以降のpanで [Intervention] Ignored attempt to cancel a touchmove event with cancelable=false, for example because scrolling is in progress and cannot be interrupted. と怒られてしまい、ちょっとうまく動きませんでした。
I any try, cant pan twice than.
他の手段として、SUPPORT_POINTER_EVENTSをhammerjs側で無効にするという方法を見つけました。
I found other method, disabled SUPPORT POINTER EVENTS.
Angularで2.0.8のhammerjsを使っている場合、以下のようなコードをmain.tsに書くと良いでしょう。
Below code help you, if you use hammerjs v2.0.8 with Angular.
しかし、この手法をとった場合、SVG Elementの移動でtouchmoveによるスクロールの伝播が発生してしまうようです。(HammerConfigうまくやったら回避できたりするのかな?)
but, this method cannot without scroll propagation.

// ...omit
import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import * as Hammer from 'hammerjs';
// ...omit
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
const SUPPORT_TOUCH = 'ontouchstart' in window;
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
const inputClass = SUPPORT_ONLY_TOUCH ? Hammer.TouchInput : SUPPORT_TOUCH ? Hammer.TouchMouseInput : Hammer.MouseInput;
class MyHammerConfig extends HammerGestureConfig {
buildHammer(element: HTMLElement) {
return new Hammer(element, { inputClass });
}
}
@NgModule({
...omit,
providers: [{ provide: HAMMER_GESTURE_CONFIG, useClass: MyHammerConfig }]
}]
ref
@walmink Same problem on iOS and same solution. Thank you very much for posting.
I was pleasantly surprised hammer.js even worked on SVG elements when I'm only attaching hammer to the div container but couldn't figure out why pointercancel was being invoked for svg elements when it wasn't if the div contained an image instead.
Not to get too off topic but it's nice to see support being started for this very useful package by @squadette.
See also: https://stackoverflow.com/a/47561100/6535053
I added a script tag in my index.html with delete window.PointerEvent and it... just works? A little frustrated that this issue is so prevalent, and there are no fixes other than these hacks.
Most helpful comment
By digging deeper into the
pancancelandpointercancel, I found a workaround that works fine for me (but your mileage may vary):For Android browsers, It turns out that preventing the default "touchmove" event handling on the window will solve this problem for any SVG element on the page, as it will prevent the browser from noticing the touch event and assuming the user is scrolling (which triggers the
pointercancel, which triggers thepancancel). That's great news, but it also disables all scrolling behaviour on the page. What I've done instead is catching the "touchmove" event on the SVG object, so any descendants in it will pan properly. I'm not yet sure if it has any bad side effects, but so far it has meant that my panning in SVG finally works on Android browsers!Here's the straightforward code I used, though notice the need for the specific option:
I will keep this issue listed here, because I think it's something that should be handled (i.e. abstracted away) by HammerJS. For now, I hope people with a similar problem will find this and need less time debugging this one.