@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
254 lines • 9.95 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { FunctionExt } from '../../util';
import { View } from '../../view/view';
import { Graph } from '../../graph/graph';
import { Point } from '../../geometry';
var ClassName;
(function (ClassName) {
ClassName.root = 'widget-minimap';
ClassName.viewport = `${ClassName.root}-viewport`;
ClassName.zoom = `${ClassName.viewport}-zoom`;
})(ClassName || (ClassName = {}));
export class MiniMap extends View {
constructor(options) {
super();
this.options = Object.assign(Object.assign({}, Util.defaultOptions), options);
this.updateViewport = FunctionExt.debounce(this.updateViewport.bind(this), 0);
this.container = document.createElement('div');
this.$container = this.$(this.container).addClass(this.prefixClassName(ClassName.root));
const graphContainer = document.createElement('div');
this.container.appendChild(graphContainer);
this.$viewport = this.$('<div>').addClass(this.prefixClassName(ClassName.viewport));
if (this.options.scalable) {
this.zoomHandle = this.$('<div>')
.addClass(this.prefixClassName(ClassName.zoom))
.appendTo(this.$viewport)
.get(0);
}
this.$container.append(this.$viewport).css({
width: this.options.width,
height: this.options.height,
padding: this.options.padding,
});
if (this.options.container) {
this.options.container.appendChild(this.container);
}
this.sourceGraph = this.graph;
const targetGraphOptions = Object.assign(Object.assign({}, this.options.graphOptions), { container: graphContainer, model: this.sourceGraph.model, frozen: true, async: this.sourceGraph.isAsync(), interacting: false, grid: false, background: false, rotating: false, resizing: false, embedding: false, selecting: false, snapline: false, clipboard: false, history: false, scroller: false });
this.targetGraph = this.options.createGraph
? this.options.createGraph(targetGraphOptions)
: new Graph(targetGraphOptions);
this.targetGraph.renderer.unfreeze();
this.updatePaper(this.sourceGraph.options.width, this.sourceGraph.options.height);
this.startListening();
}
get graph() {
return this.options.graph;
}
get scroller() {
return this.graph.scroller.widget;
}
get graphContainer() {
if (this.scroller) {
return this.scroller.container;
}
return this.graph.container;
}
get $graphContainer() {
if (this.scroller) {
return this.scroller.$container;
}
return this.$(this.graph.container);
}
startListening() {
if (this.scroller) {
this.$graphContainer.on(`scroll${this.getEventNamespace()}`, this.updateViewport);
}
else {
this.sourceGraph.on('translate', this.updateViewport, this);
}
this.sourceGraph.on('resize', this.updatePaper, this);
this.delegateEvents({
mousedown: 'startAction',
touchstart: 'startAction',
[`mousedown .${this.prefixClassName('graph')}`]: 'scrollTo',
[`touchstart .${this.prefixClassName('graph')}`]: 'scrollTo',
});
}
stopListening() {
if (this.scroller) {
this.$graphContainer.off(this.getEventNamespace());
}
else {
this.sourceGraph.off('translate', this.updateViewport, this);
}
this.sourceGraph.off('resize', this.updatePaper, this);
this.undelegateEvents();
}
onRemove() {
this.targetGraph.view.remove();
this.stopListening();
this.targetGraph.dispose();
}
updatePaper(w, h) {
let width;
let height;
if (typeof w === 'object') {
width = w.width;
height = w.height;
}
else {
width = w;
height = h;
}
const origin = this.sourceGraph.options;
const scale = this.sourceGraph.transform.getScale();
const maxWidth = this.options.width - 2 * this.options.padding;
const maxHeight = this.options.height - 2 * this.options.padding;
width /= scale.sx; // eslint-disable-line
height /= scale.sy; // eslint-disable-line
this.ratio = Math.min(maxWidth / width, maxHeight / height);
const ratio = this.ratio;
const x = (origin.x * ratio) / scale.sx;
const y = (origin.y * ratio) / scale.sy;
width *= ratio; // eslint-disable-line
height *= ratio; // eslint-disable-line
this.targetGraph.resizeGraph(width, height);
this.targetGraph.translate(x, y);
this.targetGraph.scale(ratio, ratio);
this.updateViewport();
return this;
}
updateViewport() {
const ratio = this.ratio;
const scale = this.sourceGraph.transform.getScale();
let origin = null;
if (this.scroller) {
origin = this.scroller.clientToLocalPoint(0, 0);
}
else {
const ctm = this.sourceGraph.matrix();
origin = new Point(-ctm.e / ctm.a, -ctm.f / ctm.d);
}
const position = this.$(this.targetGraph.container).position();
const translation = this.targetGraph.translate();
translation.ty = translation.ty || 0;
this.geometry = {
top: position.top + origin.y * ratio + translation.ty,
left: position.left + origin.x * ratio + translation.tx,
width: (this.$graphContainer.innerWidth() * ratio) / scale.sx,
height: (this.$graphContainer.innerHeight() * ratio) / scale.sy,
};
this.$viewport.css(this.geometry);
}
startAction(evt) {
const e = this.normalizeEvent(evt);
const action = e.target === this.zoomHandle ? 'zooming' : 'panning';
const { tx, ty } = this.sourceGraph.translate();
const eventData = {
action,
clientX: e.clientX,
clientY: e.clientY,
scrollLeft: this.graphContainer.scrollLeft,
scrollTop: this.graphContainer.scrollTop,
zoom: this.sourceGraph.zoom(),
scale: this.sourceGraph.transform.getScale(),
geometry: this.geometry,
translateX: tx,
translateY: ty,
};
this.delegateDocumentEvents(Util.documentEvents, eventData);
}
doAction(evt) {
const e = this.normalizeEvent(evt);
const clientX = e.clientX;
const clientY = e.clientY;
const data = e.data;
switch (data.action) {
case 'panning': {
const scale = this.sourceGraph.transform.getScale();
const rx = (clientX - data.clientX) * scale.sx;
const ry = (clientY - data.clientY) * scale.sy;
if (this.scroller) {
this.graphContainer.scrollLeft = data.scrollLeft + rx / this.ratio;
this.graphContainer.scrollTop = data.scrollTop + ry / this.ratio;
}
else {
this.sourceGraph.translate(data.translateX - rx / this.ratio, data.translateY - ry / this.ratio);
}
break;
}
case 'zooming': {
const startScale = data.scale;
const startGeometry = data.geometry;
const delta = 1 + (data.clientX - clientX) / startGeometry.width / startScale.sx;
if (data.frameId) {
cancelAnimationFrame(data.frameId);
}
data.frameId = requestAnimationFrame(() => {
this.sourceGraph.zoom(delta * data.zoom, {
absolute: true,
minScale: this.options.minScale,
maxScale: this.options.maxScale,
});
});
break;
}
default:
break;
}
}
stopAction() {
this.undelegateDocumentEvents();
}
scrollTo(evt) {
const e = this.normalizeEvent(evt);
let x;
let y;
const ts = this.targetGraph.translate();
ts.ty = ts.ty || 0;
if (e.offsetX == null) {
const offset = this.$(this.targetGraph.container).offset();
x = e.pageX - offset.left;
y = e.pageY - offset.top;
}
else {
x = e.offsetX;
y = e.offsetY;
}
const cx = (x - ts.tx) / this.ratio;
const cy = (y - ts.ty) / this.ratio;
this.sourceGraph.centerPoint(cx, cy);
}
dispose() {
this.remove();
}
}
__decorate([
View.dispose()
], MiniMap.prototype, "dispose", null);
var Util;
(function (Util) {
Util.defaultOptions = {
width: 300,
height: 200,
padding: 10,
scalable: true,
minScale: 0.01,
maxScale: 16,
graphOptions: {},
createGraph: (options) => new Graph(options),
};
Util.documentEvents = {
mousemove: 'doAction',
touchmove: 'doAction',
mouseup: 'stopAction',
touchend: 'stopAction',
};
})(Util || (Util = {}));
//# sourceMappingURL=index.js.map