From d2cb4aceb42397b63c2485ebc86c9ad69bf22ede Mon Sep 17 00:00:00 2001 From: ratatoeskr666 Date: Sat, 5 Aug 2023 14:54:29 +0000 Subject: [PATCH] Only capture pointer when a certain threshold is exceeded Only invoke window.move() once every 5ms to prevent performance issues --- src/api/window.ts | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/api/window.ts b/src/api/window.ts index c1386da..ea111d5 100644 --- a/src/api/window.ts +++ b/src/api/window.ts @@ -102,6 +102,9 @@ export function setDraggableRegion(domElementOrId: string | HTMLElement): Promis domElementOrId : document.getElementById(domElementOrId); let initialClientX: number = 0; let initialClientY: number = 0; + let absDragMovementDistance: number = 0; + let isPointerCaptured = false; + let lastMoveTimestamp = performance.now(); if (!draggableRegion) { return reject({ @@ -122,19 +125,44 @@ export function setDraggableRegion(domElementOrId: string | HTMLElement): Promis draggableRegions.set(draggableRegion, { pointerdown: startPointerCapturing, pointerup: endPointerCapturing }); - async function onPointerMove(evt: PointerEvent) { - await move( - evt.screenX - initialClientX, - evt.screenY - initialClientY - ); + async function onPointerMove(evt: PointerEvent) { + + if (isPointerCaptured) { + + const currentMilliseconds = performance.now(); + const timeTillLastMove = currentMilliseconds - lastMoveTimestamp; + // Limit move calls to 1 per every 5ms - TODO: introduce constant instead of magic number? + if (timeTillLastMove < 5) { + // Do not execute move more often than 1x every 5ms or performance will drop + return; + } + + // Store current time minus the offset + lastMoveTimestamp = currentMilliseconds - (timeTillLastMove - 5); + + await move( + evt.screenX - initialClientX, + evt.screenY - initialClientY + ); + + return; + } + + // Add absolute drag distance + absDragMovementDistance = Math.sqrt(evt.movementX * evt.movementX + evt.movementY * evt.movementY); + // Only start pointer capturing when the user dragged more than a certain amount of distance + // This ensures that the user can also click on the dragable area, e.g. if the area is menu / navbar + if (absDragMovementDistance >= 10) { // TODO: introduce constant instead of magic number? + isPointerCaptured = true; + draggableRegion.setPointerCapture(evt.pointerId); + } } function startPointerCapturing(evt: PointerEvent) { if (evt.button !== 0) return; initialClientX = evt.clientX; initialClientY = evt.clientY; - draggableRegion.addEventListener('pointermove', onPointerMove); - draggableRegion.setPointerCapture(evt.pointerId); + draggableRegion.addEventListener('pointermove', onPointerMove); } function endPointerCapturing(evt: PointerEvent) {