From 7230806adbd719a5e2b4bd8167fc71cffbce4e29 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Sat, 25 Mar 2023 19:06:41 +0300 Subject: [PATCH] Pan + zoom! --- client/cursor.js | 50 ++++++++++++++++++++++++++++++++++++---------- client/default.css | 3 +++ client/index.js | 10 ++++++++++ 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/client/cursor.js b/client/cursor.js index 12391a5..25c08c6 100644 --- a/client/cursor.js +++ b/client/cursor.js @@ -15,8 +15,8 @@ function on_down(e) { return; } - const x = Math.round(e.clientX + window.scrollX); - const y = Math.round(e.clientY + window.scrollY); + const x = Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom); + const y = Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom); storage.state.drawing = true; @@ -37,8 +37,11 @@ function on_move(e) { const last_x = storage.cursor.x; const last_y = storage.cursor.y; - const x = storage.cursor.x = Math.round(e.clientX + window.scrollX); - const y = storage.cursor.y = Math.round(e.clientY + window.scrollY); + const x = storage.cursor.x = Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom); + const y = storage.cursor.y = Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom); + + const old_offset_x = storage.canvas.offset_x; + const old_offset_y = storage.canvas.offset_y; if (storage.state.drawing) { const width = storage.cursor.width; @@ -58,14 +61,14 @@ function on_move(e) { storage.canvas.offset_x -= e.movementX; storage.canvas.offset_y -= e.movementY; - if (window.scrollX !== storage.canvas.offset_x || window.scrollY !== storage.canvas.offset_y) { - window.scrollTo(storage.canvas.offset_x, storage.canvas.offset_y); + if (storage.canvas.offset_x !== old_offset_x || storage.canvas.offset_y !== old_offset_y) { + move_canvas(); } - if (storage.canvas.offset_x > storage.canvas.max_scroll_x) storage.canvas.offset_x = storage.canvas.max_scroll_x; - if (storage.canvas.offset_x < 0) storage.canvas.offset_x = 0; - if (storage.canvas.offset_y > storage.canvas.max_scroll_y) storage.canvas.offset_y = storage.canvas.max_scroll_y; - if (storage.canvas.offset_y < 0) storage.canvas.offset_y = 0; + // if (storage.canvas.offset_x > storage.canvas.max_scroll_x) storage.canvas.offset_x = storage.canvas.max_scroll_x; + // if (storage.canvas.offset_x < 0) storage.canvas.offset_x = 0; + // if (storage.canvas.offset_y > storage.canvas.max_scroll_y) storage.canvas.offset_y = storage.canvas.max_scroll_y; + // if (storage.canvas.offset_y < 0) storage.canvas.offset_y = 0; } e.preventDefault(); @@ -154,6 +157,33 @@ async function on_drop(e) { return false; } +function on_wheel(e) { + const x = Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom); + const y = Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom); + + const dz = (e.deltaY < 0 ? 0.1 : -0.1); + + storage.canvas.zoom += dz; + + if (storage.canvas.zoom > storage.max_zoom) { + storage.canvas.zoom = storage.max_zoom; + return; + } + + if (storage.canvas.zoom < storage.min_zoom) { + storage.canvas.zoom = storage.min_zoom; + return; + } + + const zoom_offset_x = Math.round(dz * x); + const zoom_offset_y = Math.round(dz * y); + + storage.canvas.offset_x += zoom_offset_x; + storage.canvas.offset_y += zoom_offset_y; + + move_canvas(); +} + function cancel(e) { e.preventDefault(); return false; diff --git a/client/default.css b/client/default.css index 0a1f3bb..cbde82b 100644 --- a/client/default.css +++ b/client/default.css @@ -15,6 +15,7 @@ html, body { left: 0; opacity: 1; transition: opacity .2s; + transform-origin: top left; } .canvas.white { @@ -27,6 +28,8 @@ html, body { #canvas0 { z-index: 0; + box-sizing: border-box; + border: 1px solid black; } #canvas1 { diff --git a/client/index.js b/client/index.js index c11150f..9548b3f 100644 --- a/client/index.js +++ b/client/index.js @@ -48,7 +48,11 @@ const storage = { 'desk_id': 123, + 'max_zoom': 4, + 'min_zoom': 0.2, + 'canvas': { + 'zoom': 1, 'width': 4096, 'height': 4096, 'offset_x': 0, @@ -100,6 +104,11 @@ function event_size(event) { return size; } +function move_canvas() { + elements.canvas0.style.transform = `translate(${-storage.canvas.offset_x}px, ${-storage.canvas.offset_y}px) scale(${storage.canvas.zoom})`; + elements.canvas1.style.transform = `translate(${-storage.canvas.offset_x}px, ${-storage.canvas.offset_y}px) scale(${storage.canvas.zoom})`; +} + function predraw_event(x, y) { return { 'type': EVENT.PREDRAW, @@ -175,6 +184,7 @@ function main() { window.addEventListener('keydown', on_keydown); window.addEventListener('keyup', on_keyup); window.addEventListener('resize', on_resize); + window.addEventListener('wheel', on_wheel); elements.brush_color.addEventListener('input', update_brush); elements.brush_width.addEventListener('input', update_brush);