I’m trying to find a better way to avoid scroll hijacking on 3D models embedded on a webpage. My idea is something similar to how Google Maps handles this:
- if there’s a mouse, the mousewheel should only zoom if
ctrl
is pressed. - on touch devices, use a two-finger drag to rotate, and a pinch to zoom. Single finger drag performs normal page scrolling as usual.
- a HTML overlay shows helpful messages (like “use two fingers to rotate” or “ctrl-scroll to zoom”) on mouse hover but when no interaction is being performed, with a timeout to show again after an interaction is made, and on single finger scroll on the canvas.
I got the mouse wheel part working by camera.inputs.remove(camera.inputs.attached.mousewheel);
plus some code to handle the wheel directly, pasted reference for developers who run into this page in the future:
this.container.addEventListener('wheel', (e) => {
if (e.ctrlKey) {
this.camera.radius += e.deltaY / 12.0; // magic constant gathered from babylonjs code
e.preventDefault();
}
});
I can handle the “use ctrl-scroll” overlay message with an else
there easily.
For mobile things seem a bit nastier. I can allow normal page scrolling with engine.doNotHandleTouchAction = true;
and touch-action: auto
. But then pinching also zooms the entire page, and I can’t find a way to disable single-finger behavior. Any suggestions, or will I need to write a new class similar to arcRotateCameraPointersInput
?
BTW, this seems quite useful to me and perhaps could be an easy to make setting for the Viewer (or even the engine itself) with a helper function. Any page that embeds 3D content will suffer from scroll hijacking, and in mobile it can pretty much get you stuck on the page. I’ll be happy to provide a PR if you like the idea.