Files
lan-manager/web/node_modules/@antv/g6-plugin/es/minimap/index.js
openclaw 0a5f6a8047 Initial commit: Lan-manager project code
- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs

Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
2026-04-20 00:52:58 +08:00

662 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;