- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
662 lines
23 KiB
JavaScript
662 lines
23 KiB
JavaScript
var __extends = this && this.__extends || function () {
|
||
var _extendStatics = function extendStatics(d, b) {
|
||
_extendStatics = Object.setPrototypeOf || {
|
||
__proto__: []
|
||
} instanceof Array && function (d, b) {
|
||
d.__proto__ = b;
|
||
} || function (d, b) {
|
||
for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
|
||
};
|
||
return _extendStatics(d, b);
|
||
};
|
||
return function (d, b) {
|
||
if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||
_extendStatics(d, b);
|
||
function __() {
|
||
this.constructor = d;
|
||
}
|
||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
};
|
||
}();
|
||
var __assign = this && this.__assign || function () {
|
||
__assign = Object.assign || function (t) {
|
||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||
s = arguments[i];
|
||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||
}
|
||
return t;
|
||
};
|
||
return __assign.apply(this, arguments);
|
||
};
|
||
import { Canvas as GCanvas } from '@antv/g-canvas';
|
||
import { Canvas as GSVGCanvas } from '@antv/g-svg';
|
||
import { isString, isNil, each, debounce } from '@antv/util';
|
||
import { createDom, modifyCSS } from '@antv/dom-util';
|
||
import { ext } from '@antv/matrix-util';
|
||
import Base from '../base';
|
||
var max = Math.max;
|
||
var transform = ext.transform;
|
||
var DEFAULT_MODE = 'default';
|
||
var KEYSHAPE_MODE = 'keyShape';
|
||
var DELEGATE_MODE = 'delegate';
|
||
var SVG = 'svg';
|
||
var MiniMap = /** @class */function (_super) {
|
||
__extends(MiniMap, _super);
|
||
function MiniMap(config) {
|
||
var _this = _super.call(this, config) || this;
|
||
/**
|
||
* 主图更新的监听函数,使用 debounce 减少渲染频率
|
||
* e.g. 拖拽节点只会在松手后的 100ms 后执行 updateCanvas
|
||
* e.g. render 时大量 addItem 也只会执行一次 updateCanvas
|
||
*/
|
||
_this.handleUpdateCanvas = debounce(function (event) {
|
||
var self = _this;
|
||
if (self.destroyed) return;
|
||
self.updateCanvas();
|
||
}, 100, false);
|
||
return _this;
|
||
}
|
||
MiniMap.prototype.getDefaultCfgs = function () {
|
||
return {
|
||
container: null,
|
||
className: 'g6-minimap',
|
||
viewportClassName: 'g6-minimap-viewport',
|
||
// Minimap 中默认展示和主图一样的内容,KeyShape 只展示节点和边的 key shape 部分,delegate表示展示自定义的rect,用户可自定义样式
|
||
type: 'default',
|
||
padding: 50,
|
||
size: [200, 120],
|
||
delegateStyle: {
|
||
fill: '#40a9ff',
|
||
stroke: '#096dd9'
|
||
},
|
||
refresh: true,
|
||
hideEdge: false
|
||
};
|
||
};
|
||
MiniMap.prototype.getEvents = function () {
|
||
return {
|
||
beforepaint: 'updateViewport',
|
||
beforeanimate: 'disableRefresh',
|
||
afteranimate: 'enableRefresh',
|
||
viewportchange: 'disableOneRefresh'
|
||
};
|
||
};
|
||
// 若是正在进行动画,不刷新缩略图
|
||
MiniMap.prototype.disableRefresh = function () {
|
||
this.set('refresh', false);
|
||
};
|
||
MiniMap.prototype.enableRefresh = function () {
|
||
this.set('refresh', true);
|
||
this.updateCanvas();
|
||
};
|
||
MiniMap.prototype.disableOneRefresh = function () {
|
||
this.set('viewportChange', true);
|
||
};
|
||
MiniMap.prototype.initViewport = function () {
|
||
var _this = this;
|
||
var cfgs = this._cfgs;
|
||
var size = cfgs.size,
|
||
graph = cfgs.graph;
|
||
if (this.destroyed) return;
|
||
var canvas = this.get('canvas');
|
||
var containerDOM = canvas.get('container');
|
||
var isFireFox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||
var isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;
|
||
var viewport = createDom("\n <div\n class=".concat(cfgs.viewportClassName, "\n style='position:absolute;\n left:0;\n top:0;\n box-sizing:border-box;\n outline: 2px solid #1980ff;\n cursor:move'\n draggable=").concat(isSafari || isFireFox ? false : true, "\n </div>"));
|
||
// 计算拖拽水平方向距离
|
||
var x = 0;
|
||
// 计算拖拽垂直方向距离
|
||
var y = 0;
|
||
// 是否在拖拽minimap的视口
|
||
var dragging = false;
|
||
// 缓存viewport当前对于画布的x
|
||
var left = 0;
|
||
// 缓存viewport当前对于画布的y
|
||
var top = 0;
|
||
// 缓存viewport当前宽度
|
||
var width = 0;
|
||
// 缓存viewport当前高度
|
||
var height = 0;
|
||
var ratio = 0;
|
||
var zoom = 0;
|
||
var dragstartevent = isSafari || isFireFox ? 'mousedown' : 'dragstart';
|
||
viewport.addEventListener(dragstartevent, function (e) {
|
||
var _a, _b;
|
||
if (e.dataTransfer) {
|
||
var img = new Image();
|
||
img.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E";
|
||
(_b = (_a = e.dataTransfer).setDragImage) === null || _b === void 0 ? void 0 : _b.call(_a, img, 0, 0);
|
||
try {
|
||
e.dataTransfer.setData('text/html', 'view-port-minimap');
|
||
} catch (_c) {
|
||
// support IE
|
||
e.dataTransfer.setData('text', 'view-port-minimap');
|
||
}
|
||
}
|
||
cfgs.refresh = false;
|
||
if (e.target !== viewport) {
|
||
return;
|
||
}
|
||
// 如果视口已经最大了,不需要拖拽
|
||
var style = viewport.style;
|
||
left = parseInt(style.left, 10);
|
||
top = parseInt(style.top, 10);
|
||
width = parseInt(style.width, 10);
|
||
height = parseInt(style.height, 10);
|
||
if (width > size[0] || height > size[1]) {
|
||
return;
|
||
}
|
||
zoom = graph.getZoom();
|
||
ratio = _this.get('ratio');
|
||
dragging = true;
|
||
x = e.clientX;
|
||
y = e.clientY;
|
||
}, false);
|
||
var dragListener = function dragListener(e) {
|
||
if (!dragging || isNil(e.clientX) || isNil(e.clientY)) {
|
||
return;
|
||
}
|
||
var dx = x - e.clientX;
|
||
var dy = y - e.clientY;
|
||
// 若视口移动到最左边或最右边了,仅移动到边界
|
||
if (left - dx < 0 || left - dx + width >= size[0]) {
|
||
dx = 0;
|
||
}
|
||
// 若视口移动到最上或最下边了,仅移动到边界
|
||
if (top - dy < 0 || top - dy + height >= size[1]) {
|
||
dy = 0;
|
||
}
|
||
left -= dx;
|
||
top -= dy;
|
||
// 先移动视口,避免移动到边上以后出现视口闪烁
|
||
modifyCSS(viewport, {
|
||
left: "".concat(left, "px"),
|
||
top: "".concat(top, "px")
|
||
});
|
||
// graph 移动需要偏移量 dx/dy * 缩放比例才会得到正确的移动距离
|
||
graph.translate(dx * zoom / ratio, dy * zoom / ratio);
|
||
x = e.clientX;
|
||
y = e.clientY;
|
||
};
|
||
if (!isSafari && !isFireFox) {
|
||
viewport.addEventListener('drag', dragListener, false);
|
||
}
|
||
var dragendListener = function dragendListener() {
|
||
dragging = false;
|
||
cfgs.refresh = true;
|
||
};
|
||
var dragendevent = isSafari || isFireFox ? 'mouseup' : 'dragend';
|
||
viewport.addEventListener(dragendevent, dragendListener, false);
|
||
containerDOM.addEventListener('mouseleave', dragendListener);
|
||
containerDOM.addEventListener('mouseup', dragendListener);
|
||
if (isSafari || isFireFox) {
|
||
containerDOM.addEventListener('mousemove', dragListener, false);
|
||
}
|
||
this.set('viewport', viewport);
|
||
containerDOM.appendChild(viewport);
|
||
};
|
||
/**
|
||
* 更新 viewport 视图
|
||
*/
|
||
MiniMap.prototype.updateViewport = function () {
|
||
if (this.destroyed) return;
|
||
var ratio = this.get('ratio');
|
||
var totaldx = this.get('totaldx');
|
||
var totaldy = this.get('totaldy');
|
||
var graph = this.get('graph');
|
||
var size = this.get('size');
|
||
var graphCanvasEl = graph.get('canvas').get('el');
|
||
var graphWidth = graph.get('width') || graphCanvasEl.scrollWidth || 500;
|
||
var graphHeight = graph.get('height') || graphCanvasEl.scrollHeight || 500;
|
||
var topLeft = graph.getPointByCanvas(0, 0);
|
||
var bottomRight = graph.getPointByCanvas(graphWidth, graphHeight);
|
||
var viewport = this.get('viewport');
|
||
if (!viewport) {
|
||
this.initViewport();
|
||
}
|
||
// viewport宽高,左上角点的计算
|
||
var width = (bottomRight.x - topLeft.x) * ratio;
|
||
var height = (bottomRight.y - topLeft.y) * ratio;
|
||
var left = topLeft.x * ratio + totaldx;
|
||
var top = topLeft.y * ratio + totaldy;
|
||
var right = left + width;
|
||
var bottom = top + height;
|
||
if (left < 0) {
|
||
width += left;
|
||
left = 0;
|
||
}
|
||
if (right > size[0]) {
|
||
width = width - (right - size[0]);
|
||
}
|
||
if (top < 0) {
|
||
height += top;
|
||
top = 0;
|
||
}
|
||
if (bottom > size[1]) {
|
||
height = height - (bottom - size[1]);
|
||
}
|
||
// 缓存目前缩放比,在移动 minimap 视窗时就不用再计算大图的移动量
|
||
this.set('ratio', ratio);
|
||
var correctLeft = "".concat(left, "px");
|
||
var correctTop = "".concat(top, "px");
|
||
modifyCSS(viewport, {
|
||
left: correctLeft,
|
||
top: correctTop,
|
||
width: "".concat(width, "px"),
|
||
height: "".concat(height, "px")
|
||
});
|
||
};
|
||
/**
|
||
* 将主图上的图形完全复制到小图
|
||
*/
|
||
MiniMap.prototype.updateGraphShapes = function () {
|
||
var graph = this._cfgs.graph;
|
||
var canvas = this.get('canvas');
|
||
var graphGroup = graph.get('group');
|
||
if (graphGroup.destroyed) return;
|
||
canvas.clear();
|
||
var clonedGroup;
|
||
if (this.get('hideEdge')) {
|
||
clonedGroup = canvas.addGroup();
|
||
graphGroup.get('children').forEach(function (group) {
|
||
if (group.get('id').includes('-edge')) return;
|
||
clonedGroup.add(group.clone());
|
||
});
|
||
} else {
|
||
clonedGroup = graphGroup.clone();
|
||
clonedGroup.resetMatrix();
|
||
canvas.add(clonedGroup);
|
||
}
|
||
// 当 renderer 是 svg,由于渲染引擎的 bug,这里需要将 visible 为 false 的元素手动隐藏
|
||
var renderer = graph.get('renderer');
|
||
if (renderer === SVG) {
|
||
// 递归更新子元素
|
||
this.updateVisible(clonedGroup);
|
||
}
|
||
};
|
||
// svg 在 canvas.add(clonedGroup) 之后会出现 visible 为 false 的元素被展示出来,需要递归更新
|
||
MiniMap.prototype.updateVisible = function (ele) {
|
||
var _this = this;
|
||
if (!ele.isGroup() && !ele.get('visible')) {
|
||
ele.hide();
|
||
} else {
|
||
var children = ele.get('children');
|
||
if (!children || !children.length) return;
|
||
children.forEach(function (child) {
|
||
if (!child.get('visible')) child.hide();
|
||
_this.updateVisible(child);
|
||
});
|
||
}
|
||
};
|
||
// 仅在 minimap 上绘制 keyShape
|
||
// FIXME 如果用户自定义绘制了其他内容,minimap上就无法画出
|
||
MiniMap.prototype.updateKeyShapes = function () {
|
||
var _this = this;
|
||
var graph = this._cfgs.graph;
|
||
var canvas = this.get('canvas');
|
||
var group = canvas.get('children')[0] || canvas.addGroup();
|
||
if (!this.get('hideEdge')) {
|
||
each(graph.getEdges(), function (edge) {
|
||
_this.updateOneEdgeKeyShape(edge, group);
|
||
});
|
||
}
|
||
each(graph.getNodes(), function (node) {
|
||
_this.updateOneNodeKeyShape(node, group);
|
||
});
|
||
var combos = graph.getCombos();
|
||
if (combos && combos.length) {
|
||
var comboGroup_1 = group.find(function (e) {
|
||
return e.get('name') === 'comboGroup';
|
||
}) || group.addGroup({
|
||
name: 'comboGroup'
|
||
});
|
||
setTimeout(function () {
|
||
if (_this.destroyed) return;
|
||
each(combos, function (combo) {
|
||
_this.updateOneComboKeyShape(combo, comboGroup_1);
|
||
});
|
||
comboGroup_1 === null || comboGroup_1 === void 0 ? void 0 : comboGroup_1.sort();
|
||
comboGroup_1 === null || comboGroup_1 === void 0 ? void 0 : comboGroup_1.toBack();
|
||
_this.updateCanvas();
|
||
}, 250);
|
||
}
|
||
this.clearDestroyedShapes();
|
||
};
|
||
/**
|
||
* 增加/更新单个元素的 keyShape
|
||
* @param item ICombo 实例
|
||
*/
|
||
MiniMap.prototype.updateOneComboKeyShape = function (item, comboGroup) {
|
||
if (this.destroyed) return;
|
||
var itemMap = this.get('itemMap') || {};
|
||
// 差量更新 minimap 上的一个节点,对应主图的 item
|
||
var mappedItem = itemMap[item.get('id')];
|
||
var bbox = item.getBBox(); // 计算了节点父组矩阵的 bbox
|
||
var cKeyShape = item.get('keyShape').clone();
|
||
var keyShapeStyle = cKeyShape.attr();
|
||
var attrs = {
|
||
x: bbox.centerX,
|
||
y: bbox.centerY
|
||
};
|
||
if (!mappedItem) {
|
||
mappedItem = cKeyShape;
|
||
comboGroup.add(mappedItem);
|
||
} else {
|
||
attrs = Object.assign(keyShapeStyle, attrs);
|
||
}
|
||
var shapeType = mappedItem.get('type');
|
||
if (shapeType === 'rect' || shapeType === 'image') {
|
||
attrs.x = bbox.minX;
|
||
attrs.y = bbox.minY;
|
||
}
|
||
mappedItem.attr(attrs);
|
||
if (!item.isVisible()) mappedItem.hide();else mappedItem.show();
|
||
mappedItem.exist = true;
|
||
var zIndex = item.getModel().depth;
|
||
if (!isNaN(zIndex)) mappedItem.set('zIndex', zIndex);
|
||
itemMap[item.get('id')] = mappedItem;
|
||
this.set('itemMap', itemMap);
|
||
};
|
||
/**
|
||
* 增加/更新单个元素的 keyShape
|
||
* @param item INode 实例
|
||
*/
|
||
MiniMap.prototype.updateOneNodeKeyShape = function (item, group) {
|
||
var itemMap = this.get('itemMap') || {};
|
||
// 差量更新 minimap 上的一个节点,对应主图的 item
|
||
var mappedItem = itemMap[item.get('id')];
|
||
var bbox = item.getBBox(); // 计算了节点父组矩阵的 bbox
|
||
var cKeyShape = item.get('keyShape').clone();
|
||
var keyShapeStyle = cKeyShape.attr();
|
||
var attrs = {
|
||
x: bbox.centerX,
|
||
y: bbox.centerY
|
||
};
|
||
if (!mappedItem) {
|
||
mappedItem = cKeyShape;
|
||
group.add(mappedItem);
|
||
} else {
|
||
attrs = Object.assign(keyShapeStyle, attrs);
|
||
mappedItem.toFront();
|
||
}
|
||
var shapeType = mappedItem.get('type');
|
||
if (shapeType === 'rect' || shapeType === 'image') {
|
||
attrs.x = bbox.minX;
|
||
attrs.y = bbox.minY;
|
||
}
|
||
mappedItem.attr(attrs);
|
||
if (!item.isVisible()) mappedItem.hide();else mappedItem.show();
|
||
mappedItem.exist = true;
|
||
var zIndex = item.getModel().depth;
|
||
if (!isNaN(zIndex)) mappedItem.set('zIndex', zIndex);
|
||
itemMap[item.get('id')] = mappedItem;
|
||
this.set('itemMap', itemMap);
|
||
};
|
||
/**
|
||
* Minimap 中展示自定义的rect,支持用户自定义样式和节点大小
|
||
*/
|
||
MiniMap.prototype.updateDelegateShapes = function () {
|
||
var _this = this;
|
||
var graph = this._cfgs.graph;
|
||
var canvas = this.get('canvas');
|
||
var group = canvas.get('children')[0] || canvas.addGroup();
|
||
// 差量更新 minimap 上的节点和边
|
||
if (!this.get('hideEdge')) {
|
||
each(graph.getEdges(), function (edge) {
|
||
_this.updateOneEdgeKeyShape(edge, group);
|
||
});
|
||
}
|
||
each(graph.getNodes(), function (node) {
|
||
_this.updateOneNodeDelegateShape(node, group);
|
||
});
|
||
var combos = graph.getCombos();
|
||
if (combos && combos.length) {
|
||
var comboGroup_2 = group.find(function (e) {
|
||
return e.get('name') === 'comboGroup';
|
||
}) || group.addGroup({
|
||
name: 'comboGroup'
|
||
});
|
||
setTimeout(function () {
|
||
if (_this.destroyed) return;
|
||
each(combos, function (combo) {
|
||
_this.updateOneComboKeyShape(combo, comboGroup_2);
|
||
});
|
||
comboGroup_2 === null || comboGroup_2 === void 0 ? void 0 : comboGroup_2.sort();
|
||
comboGroup_2 === null || comboGroup_2 === void 0 ? void 0 : comboGroup_2.toBack();
|
||
_this.updateCanvas();
|
||
}, 250);
|
||
}
|
||
this.clearDestroyedShapes();
|
||
};
|
||
MiniMap.prototype.clearDestroyedShapes = function () {
|
||
var itemMap = this.get('itemMap') || {};
|
||
var keys = Object.keys(itemMap);
|
||
if (!keys || keys.length === 0) return;
|
||
for (var i = keys.length - 1; i >= 0; i--) {
|
||
var shape = itemMap[keys[i]];
|
||
var exist = shape.exist;
|
||
shape.exist = false;
|
||
if (!exist) {
|
||
shape.remove();
|
||
delete itemMap[keys[i]];
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* 设置只显示 edge 的 keyShape
|
||
* @param item IEdge 实例
|
||
*/
|
||
MiniMap.prototype.updateOneEdgeKeyShape = function (item, group) {
|
||
var itemMap = this.get('itemMap') || {};
|
||
// 差量更新 minimap 上的一个节点,对应主图的 item
|
||
var mappedItem = itemMap[item.get('id')];
|
||
if (mappedItem) {
|
||
var path = item.get('keyShape').attr('path');
|
||
mappedItem.attr('path', path);
|
||
} else {
|
||
mappedItem = item.get('keyShape').clone();
|
||
group.add(mappedItem);
|
||
}
|
||
if (!item.isVisible()) mappedItem.hide();else mappedItem.show();
|
||
mappedItem.exist = true;
|
||
itemMap[item.get('id')] = mappedItem;
|
||
this.set('itemMap', itemMap);
|
||
};
|
||
/**
|
||
* Minimap 中展示自定义的 rect,支持用户自定义样式和节点大小
|
||
* 增加/更新单个元素
|
||
* @param item INode 实例
|
||
*/
|
||
MiniMap.prototype.updateOneNodeDelegateShape = function (item, group) {
|
||
var delegateStyle = this.get('delegateStyle');
|
||
var itemMap = this.get('itemMap') || {};
|
||
// 差量更新 minimap 上的一个节点,对应主图的 item
|
||
var mappedItem = itemMap[item.get('id')];
|
||
var bbox = item.getBBox(); // 计算了节点父组矩阵的 bbox
|
||
if (mappedItem) {
|
||
var attrs = {
|
||
x: bbox.minX,
|
||
y: bbox.minY,
|
||
width: bbox.width,
|
||
height: bbox.height
|
||
};
|
||
mappedItem.attr(attrs);
|
||
mappedItem.toFront();
|
||
} else {
|
||
mappedItem = group.addShape('rect', {
|
||
attrs: __assign({
|
||
x: bbox.minX,
|
||
y: bbox.minY,
|
||
width: bbox.width,
|
||
height: bbox.height
|
||
}, delegateStyle),
|
||
name: 'minimap-node-shape'
|
||
});
|
||
}
|
||
if (!item.isVisible()) mappedItem.hide();else mappedItem.show();
|
||
mappedItem.exist = true;
|
||
itemMap[item.get('id')] = mappedItem;
|
||
this.set('itemMap', itemMap);
|
||
};
|
||
MiniMap.prototype.init = function () {
|
||
this.initContainer();
|
||
this.get('graph').on('afterupdateitem', this.handleUpdateCanvas);
|
||
this.get('graph').on('afteritemstatechange', this.handleUpdateCanvas);
|
||
this.get('graph').on('afteradditem', this.handleUpdateCanvas);
|
||
this.get('graph').on('afterremoveitem', this.handleUpdateCanvas);
|
||
this.get('graph').on('afterrender', this.handleUpdateCanvas);
|
||
this.get('graph').on('afterlayout', this.handleUpdateCanvas);
|
||
};
|
||
/**
|
||
* 初始化 Minimap 的容器
|
||
*/
|
||
MiniMap.prototype.initContainer = function () {
|
||
var self = this;
|
||
var graph = self.get('graph');
|
||
var size = self.get('size');
|
||
var className = self.get('className');
|
||
var parentNode = self.get('container');
|
||
var container = createDom("<div class='".concat(className, "' style='width: ").concat(size[0], "px; height: ").concat(size[1], "px; overflow: hidden'></div>"));
|
||
if (isString(parentNode)) {
|
||
parentNode = document.getElementById(parentNode);
|
||
}
|
||
if (parentNode) {
|
||
parentNode.appendChild(container);
|
||
} else {
|
||
graph.get('container').appendChild(container);
|
||
}
|
||
self.set('container', container);
|
||
var containerDOM = createDom('<div class="g6-minimap-container" style="position: relative;"></div>');
|
||
container.appendChild(containerDOM);
|
||
containerDOM.addEventListener('dragenter', function (e) {
|
||
e.preventDefault();
|
||
});
|
||
containerDOM.addEventListener('dragover', function (e) {
|
||
e.preventDefault();
|
||
});
|
||
var canvas;
|
||
var renderer = graph.get('renderer');
|
||
if (renderer === SVG) {
|
||
canvas = new GSVGCanvas({
|
||
container: containerDOM,
|
||
width: size[0],
|
||
height: size[1]
|
||
});
|
||
} else {
|
||
canvas = new GCanvas({
|
||
container: containerDOM,
|
||
width: size[0],
|
||
height: size[1]
|
||
});
|
||
}
|
||
self.set('canvas', canvas);
|
||
self.updateCanvas();
|
||
};
|
||
MiniMap.prototype.updateCanvas = function () {
|
||
if (this.destroyed) return;
|
||
// 如果是在动画,则不刷新视图
|
||
var isRefresh = this.get('refresh');
|
||
if (!isRefresh) {
|
||
return;
|
||
}
|
||
var graph = this.get('graph');
|
||
if (graph.get('destroyed')) {
|
||
return;
|
||
}
|
||
// 如果是视口变换,也不刷新视图,但是需要重置视口大小和位置
|
||
if (this.get('viewportChange')) {
|
||
this.set('viewportChange', false);
|
||
this.updateViewport();
|
||
}
|
||
var size = this.get('size'); // 用户定义的 minimap size
|
||
var canvas = this.get('canvas'); // minimap 的 canvas
|
||
var type = this.get('type'); // minimap 的类型
|
||
var padding = this.get('padding'); // 用户额定义的 minimap 的 padding
|
||
if (canvas.destroyed) {
|
||
return;
|
||
}
|
||
switch (type) {
|
||
case DEFAULT_MODE:
|
||
this.updateGraphShapes();
|
||
break;
|
||
case KEYSHAPE_MODE:
|
||
this.updateKeyShapes();
|
||
break;
|
||
case DELEGATE_MODE:
|
||
// 得到的节点直接带有 x 和 y,每个节点不存在父 group,即每个节点位置不由父 group 控制
|
||
this.updateDelegateShapes();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
var group = canvas.get('children')[0];
|
||
if (!group) return;
|
||
group.resetMatrix();
|
||
// 该 bbox 是准确的,不计算 matrix 的包围盒
|
||
var bbox = group.getCanvasBBox();
|
||
var graphBBox = graph.get('canvas').getCanvasBBox(); // 主图的 bbox
|
||
var graphZoom = graph.getZoom() || 1;
|
||
var width = graphBBox.width / graphZoom;
|
||
var height = graphBBox.height / graphZoom;
|
||
if (Number.isFinite(bbox.width)) {
|
||
// 刷新后bbox可能会变,需要重置画布矩阵以缩放到合适的大小
|
||
width = max(bbox.width, width);
|
||
height = max(bbox.height, height);
|
||
}
|
||
width += 2 * padding;
|
||
height += 2 * padding;
|
||
var ratio = Math.min(size[0] / width, size[1] / height);
|
||
var matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||
var minX = 0;
|
||
var minY = 0;
|
||
// 平移到左上角
|
||
if (Number.isFinite(bbox.minX)) {
|
||
minX = -bbox.minX;
|
||
}
|
||
if (Number.isFinite(bbox.minY)) {
|
||
minY = -bbox.minY;
|
||
}
|
||
// 缩放到适合视口后, 平移到画布中心
|
||
var dx = (size[0] - (width - 2 * padding) * ratio) / 2;
|
||
var dy = (size[1] - (height - 2 * padding) * ratio) / 2;
|
||
matrix = transform(matrix, [['t', minX, minY], ['s', ratio, ratio], ['t', dx, dy] // 移动到画布中心
|
||
]);
|
||
group.setMatrix(matrix);
|
||
// 更新minimap视口
|
||
this.set('ratio', ratio);
|
||
this.set('totaldx', dx + minX * ratio);
|
||
this.set('totaldy', dy + minY * ratio);
|
||
this.set('dx', dx);
|
||
this.set('dy', dy);
|
||
this.updateViewport();
|
||
};
|
||
/**
|
||
* 获取minimap的画布
|
||
* @return {GCanvas} G的canvas实例
|
||
*/
|
||
MiniMap.prototype.getCanvas = function () {
|
||
return this.get('canvas');
|
||
};
|
||
/**
|
||
* 获取minimap的窗口
|
||
* @return {HTMLElement} 窗口的dom实例
|
||
*/
|
||
MiniMap.prototype.getViewport = function () {
|
||
return this.get('viewport');
|
||
};
|
||
/**
|
||
* 获取minimap的容器dom
|
||
* @return {HTMLElement} dom
|
||
*/
|
||
MiniMap.prototype.getContainer = function () {
|
||
return this.get('container');
|
||
};
|
||
MiniMap.prototype.destroy = function () {
|
||
var _a;
|
||
(_a = this.get('canvas')) === null || _a === void 0 ? void 0 : _a.destroy();
|
||
var container = this.get('container');
|
||
if (container === null || container === void 0 ? void 0 : container.parentNode) container.parentNode.removeChild(container);
|
||
};
|
||
return MiniMap;
|
||
}(Base);
|
||
export default MiniMap; |