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); } }