Add pinch-to-zoom

This commit is contained in:
Jonathan Tran
2024-09-23 12:47:02 -04:00
parent 24c2fe996f
commit a8d12a35cd
2 changed files with 29 additions and 5 deletions

View File

@ -531,6 +531,10 @@ export class CameraControls {
} }
zoomDirection = (event: WheelEvent): 1 | -1 => { zoomDirection = (event: WheelEvent): 1 | -1 => {
if (this.interactionGuards.zoom.pinchToZoom && isPinchToZoom(event)) {
return 1
}
if (!this.interactionGuards.zoom.scrollAllowInvertY) return 1 if (!this.interactionGuards.zoom.scrollAllowInvertY) return 1
// Safari provides the updated user setting on every event, so it's more // Safari provides the updated user setting on every event, so it's more
// accurate than our cached value. // accurate than our cached value.
@ -1365,11 +1369,17 @@ function _getInteractionType(
enableZoom: boolean enableZoom: boolean
): interactionType | 'none' { ): interactionType | 'none' {
if (event instanceof WheelEvent) { if (event instanceof WheelEvent) {
if (enablePan && interactionGuards.pan.scrollCallback(event)) return 'pan' // If the control scheme accepts pinch-to-zoom, and the event is
if (enableRotate && interactionGuards.rotate.scrollCallback(event)) // pinch-to-zoom, never consider other interaction types.
return 'rotate' if (interactionGuards.zoom.pinchToZoom && isPinchToZoom(event)) {
if (enableZoom && interactionGuards.zoom.scrollCallback(event)) if (enableZoom) return 'zoom'
return 'zoom' } else {
if (enablePan && interactionGuards.pan.scrollCallback(event)) return 'pan'
if (enableRotate && interactionGuards.rotate.scrollCallback(event))
return 'rotate'
if (enableZoom && interactionGuards.zoom.scrollCallback(event))
return 'zoom'
}
} else { } else {
if (enablePan && interactionGuards.pan.callback(event)) return 'pan' if (enablePan && interactionGuards.pan.callback(event)) return 'pan'
if (enableRotate && interactionGuards.rotate.callback(event)) if (enableRotate && interactionGuards.rotate.callback(event))
@ -1379,6 +1389,18 @@ function _getInteractionType(
return 'none' return 'none'
} }
function isPinchToZoom(event: WheelEvent): boolean {
// Browsers do this hack. A couple issues:
//
// - According to MDN, it doesn't work on iOS.
// - It doesn't differentiate with a user actually holding Control and
// scrolling normally. It's possible to detect this by using onKeyDown and
// onKeyUp to track the state of the Control key. But we currently don't
// care about this since only the Apple Trackpad scheme looks for
// pinch-to-zoom events using interactionGuards.zoom.pinchToZoom.
return event.ctrlKey
}
/** /**
* Tells the engine to fire it's animation waits for it to finish and then requests camera settings * Tells the engine to fire it's animation waits for it to finish and then requests camera settings
* to ensure the client-side camera is synchronized with the engine's camera state. * to ensure the client-side camera is synchronized with the engine's camera state.

View File

@ -67,6 +67,7 @@ interface MouseGuardZoomHandler {
dragCallback: (e: MouseEvent) => boolean dragCallback: (e: MouseEvent) => boolean
scrollCallback: (e: WheelEvent) => boolean scrollCallback: (e: WheelEvent) => boolean
scrollAllowInvertY?: boolean scrollAllowInvertY?: boolean
pinchToZoom?: boolean
lenientDragStartButton?: number lenientDragStartButton?: number
} }
@ -158,6 +159,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
!e.altKey && !e.altKey &&
!e.metaKey, !e.metaKey,
scrollAllowInvertY: true, scrollAllowInvertY: true,
pinchToZoom: true,
}, },
rotate: { rotate: {
description: `${ALT} + Scroll`, description: `${ALT} + Scroll`,