From c13e5a684814d717a4a48f3babf84a7b5aa86868 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Sun, 5 May 2024 01:09:15 +0300 Subject: [PATCH] Smooth zooming --- README.txt | 6 ++++-- client/index.js | 2 ++ client/webgl_draw.js | 20 ++++++++++++++++++++ client/webgl_listeners.js | 20 +++++--------------- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/README.txt b/README.txt index 8e8197f..7a99dad 100644 --- a/README.txt +++ b/README.txt @@ -17,6 +17,7 @@ Release: + Stroke previews get connected when drawn without panning on touch devices + Redraw HTML (cursors) on local canvas moves + New strokes dissapear on the HMH desk + - Color picker misses on strange line endings - Debug - Restore ability to limit event range * Listeners/events/multiplayer @@ -24,6 +25,7 @@ Release: + Fix blinking own stroke inbetween SYN->server and SYN->client + Drag with mouse button 3 + Investigate skipped inputs on mobile (panning, zooming) [Events were not actually getting skipped. The stroke previews were just not being drawn] + + Smooth zoom - Be able to have multiple "current" strokes per player. In case of bad internet this can happen! - Do NOT use session id as player id LUL - Save events to indexeddb (as some kind of a blob), restore on reconnect and page reload @@ -35,7 +37,7 @@ Release: + Follow player + Color picker (or at the very least an Open Color color pallete) + EYE DROPPER! - - Dynamic svg cursor to represent the brush + * Dynamic svg cursor to represent the brush - Eraser - Line drawing - Undo/redo @@ -46,7 +48,7 @@ Release: - Set up VAOs - We are calling "geometry_prepare_stroke" twice for some reason - Presentation / "marketing" - - Title + - Title (InfiNotes?) - Icon - Product page (github readme, demo videos) diff --git a/client/index.js b/client/index.js index 0d220d8..6b23fe6 100644 --- a/client/index.js +++ b/client/index.js @@ -142,6 +142,8 @@ async function main() { 'offset': { 'x': 0, 'y': 0 }, 'zoom_level': 0, 'zoom': 1.0, + 'target_zoom': 1.0, + 'zoom_screenp': {'x': 0, 'y': 0}, }, 'cursor': { diff --git a/client/webgl_draw.js b/client/webgl_draw.js index 2ff67a4..fddde52 100644 --- a/client/webgl_draw.js +++ b/client/webgl_draw.js @@ -289,4 +289,24 @@ async function draw(state, context) { schedule_draw(state, context); } } + + if (state.canvas.target_zoom != state.canvas.zoom) { + update_canvas_zoom(state, state.canvas.zoom, state.canvas.target_zoom); + schedule_draw(state, context); + } +} + +function update_canvas_zoom(state, current, target) { + if (Math.abs(1.0 - current / target) > 0.01) { + state.canvas.zoom = current + (target - current) * 0.2; + } else { + state.canvas.zoom = target; + } + + // https://gist.github.com/aolo2/a373363419bd5a9283977ab9f8841f78 + const zc = state.canvas.zoom_screenp; + state.canvas.offset.x = zc.x - (zc.x - state.canvas.offset.x) * state.canvas.zoom / current; + state.canvas.offset.y = zc.y - (zc.y - state.canvas.offset.y) * state.canvas.zoom / current; + + update_cursor(state); } diff --git a/client/webgl_listeners.js b/client/webgl_listeners.js index 816058b..7b3d0a6 100644 --- a/client/webgl_listeners.js +++ b/client/webgl_listeners.js @@ -393,8 +393,6 @@ function update_cursor(state) { function wheel(e, state, context) { const screenp = {'x': window.devicePixelRatio * e.clientX, 'y': window.devicePixelRatio * e.clientY}; - const canvasp = screen_to_canvas(state, screenp); - const zooming_in = e.deltaY < 0; const zoom_level = zooming_in ? state.canvas.zoom_level + 1 : state.canvas.zoom_level - 1; @@ -402,24 +400,16 @@ function wheel(e, state, context) { return; } - state.canvas.zoom_level = zoom_level; - const dz = (zoom_level > 0 ? config.zoom_delta : -config.zoom_delta); - const old_zoom = state.canvas.zoom; - const new_zoom = Math.pow(1.0 + dz, Math.abs(zoom_level)) - + state.canvas.zoom_level = zoom_level; + state.canvas.target_zoom = Math.pow(1.0 + dz, Math.abs(zoom_level)) + state.canvas.zoom_screenp = screenp; + // If we are moving our canvas, we don't need to follow anymore if (state.following_player !== null) { toggle_follow_player(state, state.following_player); } - - // https://gist.github.com/aolo2/a373363419bd5a9283977ab9f8841f78 - state.canvas.offset.x = screenp.x - (screenp.x - state.canvas.offset.x) * new_zoom / old_zoom; - state.canvas.offset.y = screenp.y - (screenp.y - state.canvas.offset.y) * new_zoom / old_zoom; - - state.canvas.zoom = new_zoom; - - update_cursor(state); + fire_event(state, movecanvas_event(state)); schedule_draw(state, context); }