Skip to content

Commit

Permalink
Add pinch-to-zoom
Browse files Browse the repository at this point in the history
  • Loading branch information
jtran committed Sep 23, 2024
1 parent a88f025 commit ee7265b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
32 changes: 27 additions & 5 deletions src/clientSideScene/CameraControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,10 @@ export class CameraControls {
}

zoomDirection = (event: WheelEvent): 1 | -1 => {
if (this.interactionGuards.zoom.pinchToZoom && isPinchToZoom(event)) {
return 1
}

if (!this.interactionGuards.zoom.scrollAllowInvertY) return 1
// Safari provides the updated user setting on every event, so it's more
// accurate than our cached value.
Expand Down Expand Up @@ -1355,11 +1359,17 @@ function _getInteractionType(
enableZoom: boolean
): interactionType | 'none' {
if (event instanceof WheelEvent) {
if (enablePan && interactionGuards.pan.scrollCallback(event)) return 'pan'
if (enableRotate && interactionGuards.rotate.scrollCallback(event))
return 'rotate'
if (enableZoom && interactionGuards.zoom.scrollCallback(event))
return 'zoom'
// If the control scheme accepts pinch-to-zoom, and the event is
// pinch-to-zoom, never consider other interaction types.
if (interactionGuards.zoom.pinchToZoom && isPinchToZoom(event)) {
if (enableZoom) 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 {
if (enablePan && interactionGuards.pan.callback(event)) return 'pan'
if (enableRotate && interactionGuards.rotate.callback(event))
Expand All @@ -1369,6 +1379,18 @@ function _getInteractionType(
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
* to ensure the client-side camera is synchronized with the engine's camera state.
Expand Down
2 changes: 2 additions & 0 deletions src/lib/cameraControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ interface MouseGuardZoomHandler {
dragCallback: (e: MouseEvent) => boolean
scrollCallback: (e: WheelEvent) => boolean
scrollAllowInvertY?: boolean
pinchToZoom?: boolean
lenientDragStartButton?: number
}

Expand Down Expand Up @@ -158,6 +159,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
!e.altKey &&
!e.metaKey,
scrollAllowInvertY: true,
pinchToZoom: true,
},
rotate: {
description: `${ALT} + Scroll`,
Expand Down

0 comments on commit ee7265b

Please sign in to comment.