UNPKG

@argdown/map-views

Version:

Browser-based map views for Argdown data using dagre-d3 and viz.js

81 lines 3.27 kB
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