@argdown/map-views
Version:
Browser-based map views for Argdown data using dagre-d3 and viz.js
81 lines • 3.27 kB
JavaScript
import { defaultMapState } from "./IMapState";
import { zoom, zoomIdentity } from "d3-zoom";
import defaultsDeep from "lodash.defaultsdeep";
export class ZoomManager {
constructor(onZoomChanged, graphIsBottomAligned = false, moveToDuration = 0.4) {
this.setZoom = (x, y, scale, duration) => {
if (!this.svg || !this.zoom) {
return;
}
const self = this;
this.svg
.transition()
.duration(duration)
.call(self.zoom.transform, zoomIdentity.translate(x, y).scale(scale));
};
this.state = defaultsDeep({}, defaultMapState);
this.onZoomChanged = onZoomChanged;
this.moveToDuration = moveToDuration;
this.graphIsBottomAligned = graphIsBottomAligned;
}
init(svg, svgGraph, width, height) {
this.state.size.width = width;
this.state.size.height = height;
this.svg = svg;
this.svgGraph = svgGraph;
const self = this;
this.zoom = zoom().on("zoom", function (event) {
self.svgGraph.attr("transform", event.transform);
self.state.scale = event.transform.k;
self.state.position.x = event.transform.x;
self.state.position.y = event.transform.y;
if (self.onZoomChanged) {
self.onZoomChanged({
scale: self.state.scale,
position: self.state.position,
size: self.state.size
});
}
});
this.svg.call(this.zoom).on("dblclick.zoom", null);
}
showAllAndCenterMap() {
if (!this.svg) {
return;
}
let positionInfo = this.svg.node().getBoundingClientRect();
const xScale = positionInfo.width / this.state.size.width;
const yScale = positionInfo.height / this.state.size.height;
const scale = Math.min(xScale, yScale);
const x = (positionInfo.width - this.state.size.width * scale) / 2;
const scaledHeight = this.state.size.height * scale;
let y = (positionInfo.height - scaledHeight) / 2;
if (this.graphIsBottomAligned) {
y += scaledHeight;
}
this.setZoom(x, y, scale, 0);
}
resetZoom() {
this.setZoom(this.state.position.x, this.state.position.y, this.state.scale, 0);
}
moveTo(x, y) {
this.setZoom(x, y, this.state.scale, this.moveToDuration);
}
moveToElement(element) {
let positionInfo = this.svg.node().getBoundingClientRect();
const point = convertCoordsL2L(this.svg.node(), element, this.svgGraph.node());
let x = -point.x * this.state.scale + positionInfo.width / 2;
let y = -point.y * this.state.scale + positionInfo.height / 2;
this.moveTo(x, y);
}
}
export const convertCoordsL2L = (svg, fromElem, toElem) => {
const matrixL2G = fromElem.getCTM();
const matrixG2L = toElem.getCTM().inverse();
const bBox = fromElem.getBBox();
const point = svg.createSVGPoint();
point.x = bBox.x + bBox.width / 2;
point.y = bBox.y + bBox.height / 2;
return point.matrixTransform(matrixL2G).matrixTransform(matrixG2L);
};
//# sourceMappingURL=ZoomManager.js.map