fixed zoom to fit
This commit is contained in:
parent
103fd7f694
commit
1e3efe5150
@ -86,7 +86,8 @@ export class Pointer {
|
|||||||
// Monitor wheel events
|
// Monitor wheel events
|
||||||
el.addEventListener('wheel', e => {
|
el.addEventListener('wheel', e => {
|
||||||
const factor = e.deltaY > 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR;
|
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,12 +56,13 @@ export class Sim {
|
|||||||
this.nextZoom = {x, y, factor};
|
this.nextZoom = {x, y, factor};
|
||||||
}
|
}
|
||||||
|
|
||||||
zoom({x: screenX, y: screenY, factor}) {
|
// x, y should be in Sim coordinates
|
||||||
const {x, y} = this.screenToSim(screenX, screenY);
|
zoom({x, y, factor}) {
|
||||||
// x, y are the mouse coordinates, which should be the center of the new view frame
|
// 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
|
// the new view origin should be x, y minus half the new view width and height
|
||||||
// compute new scale
|
// compute new scale
|
||||||
this.display.scalePower += factor;
|
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_MAX) this.display.scalePower = SCALE_POWER_MAX;
|
||||||
if (this.display.scalePower < SCALE_POWER_MIN) this.display.scalePower = SCALE_POWER_MIN;
|
if (this.display.scalePower < SCALE_POWER_MIN) this.display.scalePower = SCALE_POWER_MIN;
|
||||||
// compute coordinates of new view frame
|
// compute coordinates of new view frame
|
||||||
@ -71,7 +72,7 @@ export class Sim {
|
|||||||
this.pointer.clearPointerHistory();
|
this.pointer.clearPointerHistory();
|
||||||
if (this.pointer.panning) {
|
if (this.pointer.panning) {
|
||||||
this.pointer.panning = undefined;
|
this.pointer.panning = undefined;
|
||||||
// TODO: Maybe rescale velocity
|
// TODO: Maybe show velocity vectors relative to view velocity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
tool/zoom.js
21
tool/zoom.js
@ -24,21 +24,21 @@ export class Zoom extends Tool {
|
|||||||
zoomIn.innerHTML = '<h2>Zoom<br>In</h2>';
|
zoomIn.innerHTML = '<h2>Zoom<br>In</h2>';
|
||||||
zoomAll.innerHTML = '<h2>Zoom to Fit</h2>';
|
zoomAll.innerHTML = '<h2>Zoom to Fit</h2>';
|
||||||
|
|
||||||
zoomOut.addEventListener('click', (e) => {
|
zoomOut.addEventListener('click', () => {
|
||||||
// Aim at center of view
|
// Aim at center of view
|
||||||
const x = this.sim.display.width * this.sim.display.scale / 2;
|
const x = this.sim.display.width * this.sim.display.scale / 2;
|
||||||
const y = this.sim.display.height * 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
|
// Aim at center of view
|
||||||
const x = this.sim.display.width * this.sim.display.scale / 2;
|
const x = this.sim.display.width * this.sim.display.scale / 2;
|
||||||
const y = this.sim.display.height * 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
|
// Determine bounding box
|
||||||
const box = this.sim.objects.boundingBox;
|
const box = this.sim.objects.boundingBox;
|
||||||
const x = (box.start.x + box.end.x) / 2;
|
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 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 heightRatio = Math.abs(box.start.y - box.end.y) / this.sim.display.height;
|
||||||
const biggerRatio = Math.max(widthRatio, heightRatio);
|
const biggerRatio = Math.max(widthRatio, heightRatio);
|
||||||
if (biggerRatio <= 1) {
|
const base2factor = Math.log(1/biggerRatio) / Math.log(2);
|
||||||
const base2Ratio = Math.log(1/biggerRatio) / Math.log(2);
|
const factor = Math.floor(base2factor) - 1;
|
||||||
this.sim.scheduleZoom({x, y}, Math.floor(base2Ratio));
|
console.log({biggerRatio, base2factor, factor});
|
||||||
} else {
|
this.sim.scheduleZoom({x, y}, factor);
|
||||||
const base2Ratio = Math.log(1/biggerRatio) / Math.log(2);
|
|
||||||
this.sim.scheduleZoom({x, y}, Math.ceil(base2Ratio));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user