From 1a8900de1f46efcefb79c34a7c215529785f96c4 Mon Sep 17 00:00:00 2001 From: Lasse Lauwerys <65569591+Iemand005@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:19:59 +0100 Subject: [PATCH] Improved touch support (#1519) * Improved touch support * Fix touch support scaling error --- src/extensions/core/simpleTouchSupport.ts | 69 +++++++++++++++++++---- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/src/extensions/core/simpleTouchSupport.ts b/src/extensions/core/simpleTouchSupport.ts index 33d9ac3e5..43f5ff894 100644 --- a/src/extensions/core/simpleTouchSupport.ts +++ b/src/extensions/core/simpleTouchSupport.ts @@ -11,7 +11,7 @@ app.registerExtension({ let zoomPos let touchTime let lastTouch - + let lastScale function getMultiTouchPos(e) { return Math.hypot( e.touches[0].clientX - e.touches[1].clientX, @@ -19,11 +19,19 @@ app.registerExtension({ ) } + function getMultiTouchCenter(e) { + return { + clientX: (e.touches[0].clientX + e.touches[1].clientX) / 2, + clientY: (e.touches[0].clientY + e.touches[1].clientY) / 2 + } + } + app.canvasEl.addEventListener( 'touchstart', - (e) => { + (e: TouchEvent) => { touchCount++ lastTouch = null + lastScale = null if (e.touches?.length === 1) { // Store start time for press+hold for context menu touchTime = new Date() @@ -32,6 +40,9 @@ app.registerExtension({ touchTime = null if (e.touches?.length === 2) { // Store center pos for zoom + lastScale = app.canvas.ds.scale + lastTouch = getMultiTouchCenter(e) + zoomPos = getMultiTouchPos(e) app.canvas.pointer_is_down = false } @@ -41,8 +52,9 @@ app.registerExtension({ ) app.canvasEl.addEventListener('touchend', (e: TouchEvent) => { - touchZooming = false touchCount = e.touches?.length ?? touchCount - 1 + + if (e.touches?.length !== 1) touchZooming = false if (touchTime && !e.touches?.length) { if (new Date().getTime() - touchTime > 600) { try { @@ -75,19 +87,54 @@ app.registerExtension({ app.canvas.search_box?.close() const newZoomPos = getMultiTouchPos(e) - const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2 - const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2 + const center = getMultiTouchCenter(e) let scale = app.canvas.ds.scale const diff = zoomPos - newZoomPos - if (diff > 0.5) { - scale *= 1 / 1.07 - } else if (diff < -0.5) { - scale *= 1.07 + + scale = lastScale - diff / 100 + + const newX = ((center.clientX - lastTouch.clientX) * 1) / scale + const newY = ((center.clientY - lastTouch.clientY) * 1) / scale + + const convertCanvasToOffset = (pos, scale) => [ + pos[0] / scale - app.canvas.ds.offset[0], + pos[1] / scale - app.canvas.ds.offset[1] + ] + + // Code from LiteGraph + if (scale < app.canvas.ds.min_scale) { + scale = app.canvas.ds.min_scale + } else if (scale > app.canvas.ds.max_scale) { + scale = app.canvas.ds.max_scale } - app.canvas.ds.changeScale(scale, [midX, midY]) + + const oldScale = app.canvas.ds.scale + + app.canvas.ds.scale = scale + + if (Math.abs(app.canvas.ds.scale - 1) < 0.01) { + app.canvas.ds.scale = 1 + } + + const newScale = app.canvas.ds.scale + + var oldCenter = convertCanvasToOffset( + [center.clientX, center.clientY], + oldScale + ) + var newCenter = convertCanvasToOffset( + [center.clientX, center.clientY], + newScale + ) + + app.canvas.ds.offset[0] += newX + newCenter[0] - oldCenter[0] + app.canvas.ds.offset[1] += newY + newCenter[1] - oldCenter[1] + + lastTouch.clientX = center.clientX + lastTouch.clientY = center.clientY + app.canvas.setDirty(true, true) - zoomPos = newZoomPos } }, true