76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
import { Tool } from '../tool.js';
|
|
import {
|
|
ZOOM_IN_FACTOR,
|
|
ZOOM_OUT_FACTOR,
|
|
WIDE_CLASSNAME,
|
|
TALL_CLASSNAME,
|
|
TOOL_INFO_CLASSNAME,
|
|
} from '../config.js';
|
|
|
|
export class Zoom extends Tool {
|
|
get displayScaleText() {
|
|
return `Scale: ${this.sim.getScaleDisplay()}`;
|
|
}
|
|
|
|
constructor(container) {
|
|
super(container);
|
|
|
|
const currentScale = document.createElement('button')
|
|
const zoomOut = document.createElement('button');
|
|
const zoomIn = document.createElement('button');
|
|
const zoomAll = document.createElement('button');
|
|
|
|
this.div.appendChild(currentScale);
|
|
this.div.appendChild(zoomOut);
|
|
this.div.appendChild(zoomIn);
|
|
this.div.appendChild(zoomAll);
|
|
|
|
currentScale.classList.add(WIDE_CLASSNAME);
|
|
currentScale.classList.add(TOOL_INFO_CLASSNAME);
|
|
zoomAll.classList.add(WIDE_CLASSNAME);
|
|
zoomAll.classList.add(TALL_CLASSNAME);
|
|
|
|
currentScale.innerHTML = this.displayScaleText;
|
|
zoomOut.innerHTML = 'Zoom<br>Out';
|
|
zoomIn.innerHTML = 'Zoom<br>In';
|
|
zoomAll.innerHTML = 'Zoom to Fit';
|
|
|
|
this.sim.onZoom(() => {
|
|
currentScale.innerHTML = this.displayScaleText;
|
|
});
|
|
|
|
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(this.sim.screenToSim(x, y), ZOOM_OUT_FACTOR);
|
|
});
|
|
|
|
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(this.sim.screenToSim(x, y), ZOOM_IN_FACTOR);
|
|
});
|
|
|
|
zoomAll.addEventListener('click', () => {
|
|
// Determine bounding box
|
|
const box = this.sim.system.boundingBox;
|
|
const x = (box.start.x + box.end.x) / 2;
|
|
const y = (box.start.y + box.end.y) / 2;
|
|
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 ratio = Math.max(widthRatio, heightRatio) * 2.5;
|
|
const factor = Math.ceil(Math.log2(1 / ratio));
|
|
|
|
// Determine average momentum and set panning velocity to match
|
|
const { netMomentum, totalMass } = this.sim.system.computeSystemCenter();
|
|
const netVelocity = {
|
|
x: netMomentum.x / totalMass,
|
|
y: netMomentum.y / totalMass,
|
|
};
|
|
this.sim.scheduleZoom({x, y}, factor, netVelocity)
|
|
});
|
|
}
|
|
}
|