From 1e3efe5150a59c345f9b331718bc006128d26d8a Mon Sep 17 00:00:00 2001 From: Ladd Date: Sat, 27 Dec 2025 11:51:42 -0600 Subject: [PATCH] fixed zoom to fit --- pointer.js | 3 ++- simulator.js | 7 ++++--- tool/zoom.js | 21 +++++++++------------ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/pointer.js b/pointer.js index 5eb9341..5b3e9eb 100644 --- a/pointer.js +++ b/pointer.js @@ -86,7 +86,8 @@ export class Pointer { // Monitor wheel events el.addEventListener('wheel', e => { const factor = e.deltaY > 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR; - this.sim.scheduleZoom({x: e.clientX, y: e.clientY}, factor); + const {x, y} = this.sim.screenToSim(e.clientX, e.clientY); + this.sim.scheduleZoom({x, y}, factor); }); } diff --git a/simulator.js b/simulator.js index a6b6c5a..695a1e7 100644 --- a/simulator.js +++ b/simulator.js @@ -56,12 +56,13 @@ export class Sim { this.nextZoom = {x, y, factor}; } - zoom({x: screenX, y: screenY, factor}) { - const {x, y} = this.screenToSim(screenX, screenY); + // x, y should be in Sim coordinates + zoom({x, y, factor}) { // x, y are the mouse coordinates, which should be the center of the new view frame // the new view origin should be x, y minus half the new view width and height // compute new scale this.display.scalePower += factor; + // TODO: Lossy rescaling to expand zoom range if (this.display.scalePower > SCALE_POWER_MAX) this.display.scalePower = SCALE_POWER_MAX; if (this.display.scalePower < SCALE_POWER_MIN) this.display.scalePower = SCALE_POWER_MIN; // compute coordinates of new view frame @@ -71,7 +72,7 @@ export class Sim { this.pointer.clearPointerHistory(); if (this.pointer.panning) { this.pointer.panning = undefined; - // TODO: Maybe rescale velocity + // TODO: Maybe show velocity vectors relative to view velocity } } diff --git a/tool/zoom.js b/tool/zoom.js index 2d6b993..317e488 100644 --- a/tool/zoom.js +++ b/tool/zoom.js @@ -24,21 +24,21 @@ export class Zoom extends Tool { zoomIn.innerHTML = '

Zoom
In

'; zoomAll.innerHTML = '

Zoom to Fit

'; - zoomOut.addEventListener('click', (e) => { + zoomOut.addEventListener('click', () => { // Aim at center of view const x = this.sim.display.width * this.sim.display.scale / 2; const y = this.sim.display.height * this.sim.display.scale / 2; - this.sim.scheduleZoom({x, y}, ZOOM_OUT_FACTOR); + this.sim.scheduleZoom(this.sim.screenToSim(x, y), ZOOM_OUT_FACTOR); }); - zoomIn.addEventListener('click', (e) => { + zoomIn.addEventListener('click', () => { // Aim at center of view const x = this.sim.display.width * this.sim.display.scale / 2; const y = this.sim.display.height * this.sim.display.scale / 2; - this.sim.scheduleZoom({x, y}, ZOOM_IN_FACTOR); + this.sim.scheduleZoom(this.sim.screenToSim(x, y), ZOOM_IN_FACTOR); }); - zoomAll.addEventListener('click', (e) => { + zoomAll.addEventListener('click', () => { // Determine bounding box const box = this.sim.objects.boundingBox; const x = (box.start.x + box.end.x) / 2; @@ -47,13 +47,10 @@ export class Zoom extends Tool { const widthRatio = Math.abs(box.start.x - box.end.x) / this.sim.display.width; const heightRatio = Math.abs(box.start.y - box.end.y) / this.sim.display.height; const biggerRatio = Math.max(widthRatio, heightRatio); - if (biggerRatio <= 1) { - const base2Ratio = Math.log(1/biggerRatio) / Math.log(2); - this.sim.scheduleZoom({x, y}, Math.floor(base2Ratio)); - } else { - const base2Ratio = Math.log(1/biggerRatio) / Math.log(2); - this.sim.scheduleZoom({x, y}, Math.ceil(base2Ratio)); - } + const base2factor = Math.log(1/biggerRatio) / Math.log(2); + const factor = Math.floor(base2factor) - 1; + console.log({biggerRatio, base2factor, factor}); + this.sim.scheduleZoom({x, y}, factor); } }); }