gravity/zoom.js
2026-01-03 13:10:38 -06:00

55 lines
1.4 KiB
JavaScript

import {
EVENT_ZOOM,
SCALE_POWER_MAX,
SCALE_POWER_MIN,
} from './config.js';
import {div, sub} from './vector.js';
export class Zoom {
sim = undefined;
nextZoom = undefined;
constructor(sim) {
this.sim = sim;
}
// velocity should be in Sim coordinate scale
scheduleZoom({x, y}, factor, velocity) {
this.nextZoom = {x, y, factor, velocity};
}
frame() {
if (this.nextZoom) {
this.zoom(this.nextZoom);
this.nextZoom = undefined;
}
}
// x, y should be in Sim coordinates
// velocity should be in Sim coordinate scale
zoom({x, y, factor, velocity}) {
const {display} = this.sim;
// 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
// TODO: Lossy rescaling to expand zoom range
let scalePower = display.scalePower + factor;
scalePower = Math.max(scalePower, SCALE_POWER_MIN);
scalePower = Math.min(scalePower, SCALE_POWER_MAX);
display.scalePower = scalePower;
// compute coordinates of new view frame
display.viewOrigin = sub({x, y}, div({x: display.width, y: display.height}, 2));
// TODO: If paused, set panning velocity on resume
// if (this.sim.playing && velocity) {
if (velocity) {
this.sim.panning.setVelocity(velocity);
}
const e = new CustomEvent(EVENT_ZOOM);
this.sim.div.dispatchEvent(e);
}
}