[SOLVED] HTML elements block touch-move events on Playcanvas UI elements (but not mouse-move)

Hi

Placing a Playcanvas UI element over an HTML element, blocks touch events such as “touchmove” on the Playcanvas UI element. Mouse events such as “mousemove” are not blocked, hence resulting in a different behavior on PC vs. Mobile. This mostly affects the ScrollView element.

Steps to reproduce
https://playcanvas.com/editor/scene/1904586

  • Execute the project on PC, observe scrolling works also within the HTML div.
  • Execute the project on a touch device (tested on iPhone 12), observe scrolling does not work in the div area.

Some observations:

  • setting the HTML div style to style.pointerEvents = "none" → touch scrolling works.
  • element.on(“mousemove”,…) get fired, element.on(“touchmove”) not

Why I am bothering with this weird constellation? I have 3D iframe’s placed in the scene and playcanvas menus with scrolling functionality are placed above them (in screenspace), which are not functional when an iframe (or other html elements) gets behind it.

Hope somebody can help,
Tom

The DIV that overlays the canvas needs to pass the events to the canvas. You can do it like this:

const canvas = this.app.graphicsDevice.canvas;
// example for touchstart, but you'd also want for others like touchend, etc
this.element.addEventListener('touchstart', (e) => {
    // copy the needed fields, probably those below are enough:
    const eventClone = new e.constructor(e.type, { changedTouches: e.changedTouches, touches: e.touches, target: e.target });
    canvas.dispatchEvent(eventClone);
}, false);

You should note that it won’t work great if your DIV is not full window, like in your example. It will consider as DIV is placed at top left corner, which will result in offset of the touchmove event. You’d want to have a full screen DIV or change the coordinates in the event clone.

1 Like

This works like a charm, big thank you @LeXXik

BTW: I had a workaround that inserted a fullscreen div, that I attached to the TouchDevice via app.touch.attach( ..full-div-element.. ) which also made the scrolling work but disabled the iframe interaction until the UI got closed.

With event propagation both items work beside of each other like it should. Offsetting the coordinates was not necessary even for non-fullscreen elements.

Any reason why this is necessary for touch events but not for mouse events?

Thanks again, saved my day :slight_smile:

1 Like

Not sure why the difference is there without further debugging. The engine handles touch vs mouse events differently, so could be something there. Maybe touch events have a propagation stop somewhere, outside the app. You could try digging it deeper, if you are adventurous :wink: