From 8c6a9ff47e052e39499c9a3f200b49861655af41 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Sun, 14 Apr 2024 14:22:26 +0100 Subject: [PATCH] Cancel pointer velocity while pinching (#3462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was a bug that could occur if you pinched while using the hand tool, where on pinch end the hand tool would slide the camera based on the pinching velocity. The fix is to cancel out any velocity while pinching. ### Change Type - [x] `sdk` — Changes the tldraw SDK - [x] `bugfix` — Bug fix ### Test Plan On mobile... 1. Select the hand tool. 2. Begin a pinch 3. Stop the pinch 4. The camera should stay where it is ### Release Notes - Fixed a bug that could occur while pinching with the hand tool selected. --- packages/editor/src/lib/editor/Editor.ts | 26 ++++++++++++------- .../src/lib/editor/managers/TickManager.ts | 8 +++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/lib/editor/Editor.ts b/packages/editor/src/lib/editor/Editor.ts index 24813f927..1d4d9a5fa 100644 --- a/packages/editor/src/lib/editor/Editor.ts +++ b/packages/editor/src/lib/editor/Editor.ts @@ -8168,11 +8168,16 @@ export class Editor extends EventEmitter { private _updateInputsFromEvent( info: TLPointerEventInfo | TLPinchEventInfo | TLWheelEventInfo ): void { - const { previousScreenPoint, previousPagePoint, currentScreenPoint, currentPagePoint } = - this.inputs + const { + pointerVelocity, + previousScreenPoint, + previousPagePoint, + currentScreenPoint, + currentPagePoint, + } = this.inputs const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)! - const { x: cx, y: cy, z: cz } = this.getCamera() + const { x: cx, y: cy, z: cz } = this.store.unsafeGetWithoutCapture(this.getCameraId())! const sx = info.point.x - screenBounds.x const sy = info.point.y - screenBounds.y @@ -8190,9 +8195,9 @@ export class Editor extends EventEmitter { this.inputs.isPen = info.type === 'pointer' && info.isPen - // Reset velocity on pointer down - if (info.name === 'pointer_down') { - this.inputs.pointerVelocity.set(0, 0) + // Reset velocity on pointer down, or when a pinch starts or ends + if (info.name === 'pointer_down' || this.inputs.isPinching) { + pointerVelocity.set(0, 0) } // todo: We only have to do this if there are multiple users in the document @@ -8200,14 +8205,15 @@ export class Editor extends EventEmitter { { id: TLPOINTER_ID, typeName: 'pointer', - x: currentPagePoint.x, - y: currentPagePoint.y, + x: sx, + y: sy, lastActivityTimestamp: // If our pointer moved only because we're following some other user, then don't // update our last activity timestamp; otherwise, update it to the current timestamp. info.type === 'pointer' && info.pointerId === INTERNAL_POINTER_IDS.CAMERA_MOVE - ? this.store.get(TLPOINTER_ID)?.lastActivityTimestamp ?? Date.now() - : Date.now(), + ? this.store.unsafeGetWithoutCapture(TLPOINTER_ID)?.lastActivityTimestamp ?? + this._tickManager.now + : this._tickManager.now, meta: {}, }, ]) diff --git a/packages/editor/src/lib/editor/managers/TickManager.ts b/packages/editor/src/lib/editor/managers/TickManager.ts index a3de4492e..bec7cf756 100644 --- a/packages/editor/src/lib/editor/managers/TickManager.ts +++ b/packages/editor/src/lib/editor/managers/TickManager.ts @@ -20,13 +20,13 @@ export class TickManager { cancelRaf?: null | (() => void) isPaused = true - last = 0 + now = 0 start = () => { this.isPaused = false this.cancelRaf?.() this.cancelRaf = throttleToNextFrame(this.tick) - this.last = Date.now() + this.now = Date.now() } tick = () => { @@ -35,8 +35,8 @@ export class TickManager { } const now = Date.now() - const elapsed = now - this.last - this.last = now + const elapsed = now - this.now + this.now = now this.updatePointerVelocity(elapsed) this.editor.emit('frame', elapsed)