Skip to content

Commit

Permalink
Merge pull request #421 from KhronosGroup/fix/touch_orbit
Browse files Browse the repository at this point in the history
Fix touch input
  • Loading branch information
UX3D-kanzler authored Dec 16, 2022
2 parents d192888 + f604a18 commit 6be1d4b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 34 deletions.
2 changes: 1 addition & 1 deletion app_web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
</script>


<body class="is-flex">
<body class="is-flex" style="touch-action: none">

<div class="columns">
<div class="column" id="canvasUI">
Expand Down
95 changes: 62 additions & 33 deletions app_web/src/logic/uimodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,64 +234,93 @@ class UIModel
filter(file => file !== undefined),
);

const move = fromEvent(document, 'mousemove');
const mousedown = fromEvent(inputDomElement, 'mousedown');
const cancelMouse = merge(fromEvent(document, 'mouseup'), fromEvent(document, 'mouseleave'));
const mouseMove = fromEvent(document, 'mousemove');
const mouseDown = fromEvent(inputDomElement, 'mousedown');
const mouseUp = merge(fromEvent(document, 'mouseup'), fromEvent(document, 'mouseleave'));

inputDomElement.addEventListener('mousemove', event => event.preventDefault());
inputDomElement.addEventListener('mousedown', event => event.preventDefault());
inputDomElement.addEventListener('mouseup', event => event.preventDefault());

const mouseOrbit = mousedown.pipe(
const mouseOrbit = mouseDown.pipe(
filter( event => event.button === 0 && event.shiftKey === false),
mergeMap(() => move.pipe(takeUntil(cancelMouse))),
map( mouse => ({deltaPhi: mouse.movementX, deltaTheta: mouse.movementY }))
mergeMap(() => mouseMove.pipe(
pairwise(),
map( ([oldMouse, newMouse]) => {
return {
deltaPhi: newMouse.pageX - oldMouse.pageX,
deltaTheta: newMouse.pageY - oldMouse.pageY
};
}),
takeUntil(mouseUp)
))
);

const mousePan = mousedown.pipe(
const mousePan = mouseDown.pipe(
filter( event => event.button === 1 || event.shiftKey === true),
mergeMap(() => move.pipe(takeUntil(cancelMouse))),
map( mouse => ({deltaX: mouse.movementX, deltaY: mouse.movementY }))
mergeMap(() => mouseMove.pipe(
pairwise(),
map( ([oldMouse, newMouse]) => {
return {
deltaX: newMouse.pageX - oldMouse.pageX,
deltaY: newMouse.pageY - oldMouse.pageY
};
}),
takeUntil(mouseUp)
))
);

const smbZoom = mousedown.pipe(
const smbZoom = mouseDown.pipe(
filter( event => event.button === 2),
mergeMap(() => move.pipe(takeUntil(cancelMouse))),
mergeMap(() => mouseMove.pipe(takeUntil(mouseUp))),
map( mouse => ({deltaZoom: mouse.movementY }))
);
const wheelZoom = fromEvent(inputDomElement, 'wheel').pipe(
map(wheelEvent => normalizeWheel(wheelEvent)),
map(normalizedZoom => ({deltaZoom: normalizedZoom.spinY }))
);
inputDomElement.addEventListener('onscroll', event => event.preventDefault(), false);
inputDomElement.addEventListener('scroll', event => event.preventDefault(), { passive: false });
inputDomElement.addEventListener('wheel', event => event.preventDefault(), { passive: false });
const mouseZoom = merge(smbZoom, wheelZoom);

const touchmove = fromEvent(document, 'touchmove');
const touchstart = fromEvent(inputDomElement, 'touchstart');
const touchend = merge(fromEvent(inputDomElement, 'touchend'), fromEvent(inputDomElement, 'touchcancel'));

const touchOrbit = touchstart.pipe(
filter( event => event.touches.length === 1),
mergeMap(() => touchmove.pipe(takeUntil(touchend))),
map( event => event.touches[0]),
pairwise(),
map( ([oldTouch, newTouch]) => {
return {
deltaPhi: newTouch.pageX - oldTouch.pageX,
deltaTheta: newTouch.pageY - oldTouch.pageY
};
})
filter(event => event.touches.length === 1),
mergeMap(() => touchmove.pipe(
filter(event => event.touches.length === 1),
map(event => event.touches[0]),
pairwise(),
map(([oldTouch, newTouch]) => {
return {
deltaPhi: 2.0 * (newTouch.clientX - oldTouch.clientX),
deltaTheta: 2.0 * (newTouch.clientY - oldTouch.clientY),
};
}),
takeUntil(touchend)
)),
);

const touchZoom = touchstart.pipe(
filter( event => event.touches.length === 2),
mergeMap(() => touchmove.pipe(takeUntil(touchend))),
map( event => {
const pos1 = vec2.fromValues(event.touches[0].pageX, event.touches[0].pageY);
const pos2 = vec2.fromValues(event.touches[1].pageX, event.touches[1].pageY);
return vec2.dist(pos1, pos2);
}),
pairwise(),
map( ([oldDist, newDist]) => ({ deltaZoom: newDist - oldDist }))
filter(event => event.touches.length === 2),
mergeMap(() => touchmove.pipe(
filter(event => event.touches.length === 2),
map(event => {
const pos1 = vec2.fromValues(event.touches[0].clientX, event.touches[0].clientY);
const pos2 = vec2.fromValues(event.touches[1].clientX, event.touches[1].clientY);
return vec2.dist(pos1, pos2);
}),
pairwise(),
map(([oldDist, newDist]) => ({ deltaZoom: 0.1 * (oldDist - newDist) })),
takeUntil(touchend))
),
);

inputDomElement.addEventListener('ontouchmove', event => event.preventDefault(), false);
inputDomElement.addEventListener('ontouchmove', event => event.preventDefault(), { passive: false });
inputDomElement.addEventListener('ontouchstart', event => event.preventDefault(), { passive: false });
inputDomElement.addEventListener('ontouchend', event => event.preventDefault(), { passive: false });

observables.orbit = merge(mouseOrbit, touchOrbit);
observables.pan = mousePan;
Expand Down
3 changes: 3 additions & 0 deletions app_web/src/ui/sass.scss
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ button.button
border: 0px;
padding: 0px;
background: rgb(51, 51, 51);
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
}

.canvasUIMaximize {
Expand Down

0 comments on commit 6be1d4b

Please sign in to comment.