- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
1061 lines
40 KiB
JavaScript
1061 lines
40 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);
|
||
};
|
||
var __rest = this && this.__rest || function (s, e) {
|
||
var t = {};
|
||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
|
||
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
|
||
}
|
||
return t;
|
||
};
|
||
import { isNumber, debounce } from '@antv/util';
|
||
import { Util } from '@antv/g6-core';
|
||
import { modifyCSS, createDom } from '@antv/dom-util';
|
||
import insertCss from 'insert-css';
|
||
import { Canvas } from '@antv/g-canvas';
|
||
import Base from '../base';
|
||
typeof document !== 'undefined' && insertCss("\n .g6-annotation-container {\n background-color: rgba(255, 255, 255, 0.3);\n padding: 8px;\n }\n .g6-annotation-wrapper {\n background-color: #fff;\n box-shadow: 0 0 8px rgba(0, 0, 0, 0.85);\n }\n .g6-annotation-header-wapper {\n height: fit-content;\n width: 100%;\n background-color: #5B8FF9;\n display: inline-flex;\n cursor: move;\n }\n .g6-annotation-title {\n margin: 4px 40px 4px 8px;\n cursor: text;\n min-width: 32px;\n }\n .g6-annotation-collapse {\n margin: 4px;\n cursor: pointer;\n }\n .g6-annotation-expand {\n margin: 4px;\n cursor: pointer;\n }\n .g6-annotation-close {\n margin: 4px 8px 4px 0;\n cursor: pointer;\n }\n .g6-annotation-content {\n padding: 8px;\n width: fit-content;\n cursor: text;\n word-break: break-all;\n min-width: 32px;\n }\n .g6-annotation-title-input-wrapper {\n margin: 4px 40px 4px 8px;\n }\n .g6-annotation-content-input {\n height: 100%;\n word-break: break-all;\n }\n .g6-annotation-content-input-wrapper {\n margin: 8px;\n height: 100%;\n }\n");
|
||
var CANVAS_ANNOTATION_ID = 'canvas-annotation';
|
||
var Annotation = /** @class */function (_super) {
|
||
__extends(Annotation, _super);
|
||
function Annotation(config) {
|
||
return _super.call(this, config) || this;
|
||
}
|
||
Annotation.prototype.getDefaultCfgs = function () {
|
||
return {
|
||
trigger: 'click',
|
||
editable: true,
|
||
itemHighlightState: 'highlight',
|
||
linkHighlightStyle: {
|
||
shadowColor: '#5B8FF9',
|
||
shadowBlur: 10
|
||
},
|
||
cardCfg: {
|
||
minHeight: 60,
|
||
width: 'fit-content',
|
||
height: 'fit-content',
|
||
collapseType: 'minimize',
|
||
closeType: 'hide',
|
||
borderRadius: 5,
|
||
maxTitleLength: 20
|
||
}
|
||
};
|
||
};
|
||
// class-methods-use-this
|
||
Annotation.prototype.getEvents = function () {
|
||
var events = {
|
||
'viewportchange': 'updateLinks',
|
||
'afterlayout': 'updateLinks',
|
||
'aftergraphrefreshposition': 'updateLinks',
|
||
'afterupdateitem': 'updateLink',
|
||
'afterchangedata': 'onGraphDataChange',
|
||
'afteritemvisibilitychange': 'onGraphItemVisibilityChange'
|
||
};
|
||
switch (this.get('trigger')) {
|
||
case 'click':
|
||
events = __assign(__assign({}, events), {
|
||
'node:click': 'showAnnotation',
|
||
'edge:click': 'showAnnotation'
|
||
});
|
||
}
|
||
return events;
|
||
};
|
||
Annotation.prototype.getDOMContent = function (cfg) {
|
||
if (this.destroyed) return;
|
||
var collapsed = cfg.collapsed,
|
||
maxWidth = cfg.maxWidth,
|
||
_a = cfg.title,
|
||
title = _a === void 0 ? '' : _a,
|
||
_b = cfg.content,
|
||
content = _b === void 0 ? '' : _b,
|
||
_c = cfg.borderRadius,
|
||
r = _c === void 0 ? 5 : _c;
|
||
var collapseExpandDOM = collapsed ? "<p class='g6-annotation-expand'>+</p>" : "<p class='g6-annotation-collapse'>-</p>";
|
||
var contentDOM = collapsed ? '' : " <p class='g6-annotation-content'>".concat(content, "</p>");
|
||
var closeDOM = "<p class='g6-annotation-close'>x</p>";
|
||
var borderRadius = collapsed ? "".concat(r, "px") : "".concat(r, "px ").concat(r, "px 0 0");
|
||
return "<div class=\"g6-annotation-wrapper\" style=\"border-radius: ".concat(r, "px; max-width: ").concat(maxWidth, "px\">\n <div\n class=\"g6-annotation-header-wapper\"\n style=\"border-radius: ").concat(borderRadius, ";\"\n >\n <h4 class='g6-annotation-title'>").concat(title, "</h4>\n ").concat(collapseExpandDOM, "\n ").concat(closeDOM, "\n </div>\n ").concat(contentDOM, "\n </div>");
|
||
};
|
||
Annotation.prototype.init = function () {
|
||
var self = this;
|
||
if (self.destroyed) return;
|
||
var graph = self.get('graph');
|
||
var graphCantainer = graph.getContainer();
|
||
var container = self.get('container');
|
||
var containerCfg = this.get('containerCfg');
|
||
if (containerCfg) {
|
||
container = this.createContainer();
|
||
graphCantainer.appendChild(container);
|
||
} else {
|
||
container = graphCantainer;
|
||
}
|
||
this.set('container', container);
|
||
// 绘制连接 annotation 和元素的连线的画布
|
||
var graphContainerBBox = graphCantainer.getBoundingClientRect();
|
||
var linkCanvas = new Canvas({
|
||
container: graphCantainer,
|
||
width: graphContainerBBox.right - graphContainerBBox.left,
|
||
height: graphContainerBBox.bottom - graphContainerBBox.top
|
||
});
|
||
modifyCSS(linkCanvas.get('el'), {
|
||
position: 'absolute',
|
||
top: 0,
|
||
left: 0,
|
||
pointerEvents: 'none'
|
||
});
|
||
// 需要传入 self,无法 removeEventListener,只能在内部判断 self 被销毁则不继续
|
||
window.addEventListener('resize', debounce(function () {
|
||
return self.resizeCanvas(self);
|
||
}, 100));
|
||
var linkGroup = linkCanvas.addGroup({
|
||
id: 'annotation-link-group'
|
||
});
|
||
self.set('linkGroup', linkGroup);
|
||
self.set('canvas', linkCanvas);
|
||
if (!self.get('getTitle')) {
|
||
self.set('getTitle', function (item) {
|
||
var _a;
|
||
var _b = ((_a = item === null || item === void 0 ? void 0 : item.getModel) === null || _a === void 0 ? void 0 : _a.call(item)) || {},
|
||
label = _b.label,
|
||
id = _b.id;
|
||
return label || id || '-';
|
||
});
|
||
}
|
||
if (!self.get('getContent')) {
|
||
self.set('getContent', function (item) {
|
||
var _a, _b;
|
||
if (!item) return '-';
|
||
var _c = ((_a = item.getModel) === null || _a === void 0 ? void 0 : _a.call(item)) || {},
|
||
label = _c.label,
|
||
id = _c.id;
|
||
var type = (_b = item.getType) === null || _b === void 0 ? void 0 : _b.call(item);
|
||
var suffix = type ? "".concat(type, ": ") : '';
|
||
return "".concat(suffix).concat(label || id || '');
|
||
});
|
||
}
|
||
// init with defaultData
|
||
var defaultData = self.get('defaultData');
|
||
if (defaultData) this.readData(defaultData);
|
||
};
|
||
Annotation.prototype.createContainer = function () {
|
||
var _this = this;
|
||
if (this.destroyed) return;
|
||
var containerCfg = this.get('containerCfg');
|
||
var graph = this.get('graph');
|
||
var graphContainer = graph.getContainer();
|
||
var _a = graphContainer.getBoundingClientRect(),
|
||
gLeft = _a.left,
|
||
gRight = _a.right,
|
||
gTop = _a.top,
|
||
gBottom = _a.bottom;
|
||
var graphContainerHeight = gBottom - gTop;
|
||
var graphContainerWidth = gRight - gLeft;
|
||
var _b = containerCfg.position,
|
||
position = _b === void 0 ? 'top' : _b,
|
||
_c = containerCfg.offsetX,
|
||
offsetX = _c === void 0 ? 0 : _c,
|
||
_d = containerCfg.offsetY,
|
||
offsetY = _d === void 0 ? 0 : _d,
|
||
otherStyle = __rest(containerCfg, ["position", "offsetX", "offsetY"]);
|
||
var _e = containerCfg.height,
|
||
height = _e === void 0 ? 'fit-content' : _e,
|
||
_f = containerCfg.width,
|
||
width = _f === void 0 ? graph.getWidth() : _f;
|
||
if (height === '100%') height = graphContainerHeight;
|
||
if (width === '100%') width = graphContainerWidth;
|
||
var maxHeight = 'unset',
|
||
maxWidth = 'unset';
|
||
var containerPosition = {};
|
||
switch (position) {
|
||
case 'right':
|
||
maxHeight = "".concat(graphContainerHeight, "px");
|
||
containerPosition = {
|
||
top: 0,
|
||
right: 0
|
||
};
|
||
containerPosition.right += gLeft + offsetX;
|
||
containerPosition.top += gTop + offsetY;
|
||
break;
|
||
case 'bottom':
|
||
maxWidth = "".concat(graphContainerWidth, "px");
|
||
containerPosition = {
|
||
bottom: 0,
|
||
left: 0
|
||
};
|
||
containerPosition.left += gLeft + offsetX;
|
||
containerPosition.bottom += gTop + offsetY;
|
||
break;
|
||
case 'top':
|
||
maxWidth = "".concat(graphContainerWidth, "px");
|
||
case 'left':
|
||
maxHeight = "".concat(graphContainerHeight, "px");
|
||
default:
|
||
containerPosition = {
|
||
top: 0,
|
||
left: 0
|
||
};
|
||
containerPosition.left += gLeft + offsetX;
|
||
containerPosition.top += gTop + offsetY;
|
||
break;
|
||
}
|
||
Object.keys(containerPosition).forEach(function (key) {
|
||
containerPosition[key] = "".concat(containerPosition[key], "px");
|
||
});
|
||
var container = createDom("<div class='".concat(containerCfg.className, " g6-annotation-container'></div>"));
|
||
modifyCSS(container, __assign(__assign({
|
||
position: 'absolute',
|
||
display: position === 'top' || position === 'bottom' ? 'inline-flex' : 'unset',
|
||
width: isNumber(width) ? "".concat(width, "px") : width,
|
||
height: isNumber(height) ? "".concat(height, "px") : height,
|
||
maxHeight: maxHeight,
|
||
maxWidth: maxWidth,
|
||
overflow: 'scroll'
|
||
}, containerPosition), otherStyle));
|
||
graphContainer.appendChild(container);
|
||
container.addEventListener('scroll', function (e) {
|
||
_this.updateLinks();
|
||
});
|
||
return container;
|
||
};
|
||
Annotation.prototype.resizeCanvas = function (self) {
|
||
// 仅在 resize 完成后进行调整
|
||
clearTimeout(self.resizeTimer);
|
||
self.resizeTimer = setTimeout(function () {
|
||
if (!self || self.destroyed) return;
|
||
var cBBox = self.get('container').getBoundingClientRect();
|
||
var newWidth = cBBox.right - cBBox.left;
|
||
var newHeight = cBBox.bottom - cBBox.top;
|
||
self.get('canvas').changeSize(newWidth, newHeight);
|
||
self.updateOutsideCards(self);
|
||
}, 250);
|
||
};
|
||
/**
|
||
* 更新超出视口范围的卡片位置
|
||
* @param selfObj 当前 annotation 插件对象。外部调用不需要传入该参数
|
||
*/
|
||
Annotation.prototype.updateOutsideCards = function (selfObj) {
|
||
var self = selfObj || this;
|
||
var cardInfoMap = self.get('cardInfoMap') || {};
|
||
var graph = self.get('graph');
|
||
var graphLeftTopCanvas = graph.getPointByCanvas(0, 0);
|
||
var graphRightBottomCanvas = graph.getPointByCanvas(graph.getWidth(), graph.getHeight());
|
||
var _a = graph.getClientByPoint(graphLeftTopCanvas.x, graphLeftTopCanvas.y),
|
||
graphLeft = _a.x,
|
||
graphTop = _a.y;
|
||
var _b = graph.getClientByPoint(graphRightBottomCanvas.x, graphRightBottomCanvas.y),
|
||
graphRight = _b.x,
|
||
graphBottom = _b.y;
|
||
Object.values(cardInfoMap).forEach(function (cardInfo) {
|
||
var card = cardInfo.card;
|
||
if (!card) return;
|
||
var style = card.style;
|
||
var left = px2Num(style.left);
|
||
var top = px2Num(style.top);
|
||
var _a = card.getBoundingClientRect(),
|
||
width = _a.width,
|
||
height = _a.height;
|
||
var newLeft = left;
|
||
var newTop = top;
|
||
if (left + width > graphRight - graphLeft) {
|
||
newLeft = graphRight - graphLeft - width;
|
||
}
|
||
if (left < 0) {
|
||
newLeft = 0;
|
||
}
|
||
if (top + height > graphBottom - graphTop) {
|
||
newTop = graphBottom - graphTop - height;
|
||
}
|
||
if (top < 0) {
|
||
newTop = 0;
|
||
}
|
||
modifyCSS(card, {
|
||
left: "".concat(newLeft, "px"),
|
||
top: "".concat(newTop, "px")
|
||
});
|
||
});
|
||
self.updateLinks();
|
||
};
|
||
Annotation.prototype.showAnnotation = function (evt) {
|
||
if (this.destroyed) return;
|
||
var item = evt.item;
|
||
this.toggleAnnotation(item);
|
||
};
|
||
Annotation.prototype.hideCards = function () {
|
||
var self = this;
|
||
if (self.destroyed) return;
|
||
var cardInfoMap = self.get('cardInfoMap') || {};
|
||
Object.keys(cardInfoMap).forEach(function (itemId) {
|
||
self.hideCard(itemId);
|
||
});
|
||
};
|
||
Annotation.prototype.toggleAnnotation = function (item, cfg) {
|
||
var _a, _b;
|
||
if (cfg === void 0) {
|
||
cfg = {};
|
||
}
|
||
var self = this;
|
||
if (self.destroyed) return;
|
||
var cardInfoMap = self.get('cardInfoMap') || {};
|
||
var graph = self.get('graph');
|
||
var container = self.get('container');
|
||
var containerCfg = self.get('containerCfg');
|
||
var _c = Object.assign({}, self.get('cardCfg') || {}, cfg),
|
||
minHeight = _c.minHeight,
|
||
minWidth = _c.minWidth,
|
||
width = _c.width,
|
||
height = _c.height,
|
||
_d = _c.collapsed,
|
||
collapsed = _d === void 0 ? false : _d,
|
||
propsX = _c.x,
|
||
propsY = _c.y,
|
||
propsTitle = _c.title,
|
||
propsContent = _c.content,
|
||
maxTitleLength = _c.maxTitleLength,
|
||
defaultBegin = _c.defaultBegin,
|
||
otherCardCfg = __rest(_c, ["minHeight", "minWidth", "width", "height", "collapsed", "x", "y", "title", "content", "maxTitleLength", "defaultBegin"]);
|
||
var linkGroup = self.get('linkGroup');
|
||
var rows = this.get('rows') || [[]];
|
||
var isCanvas = (_a = item.isCanvas) === null || _a === void 0 ? void 0 : _a.call(item);
|
||
var itemId = isCanvas ? CANVAS_ANNOTATION_ID : item.getID();
|
||
var _e = cardInfoMap[itemId] || {},
|
||
card = _e.card,
|
||
link = _e.link,
|
||
x = _e.x,
|
||
y = _e.y,
|
||
title = _e.title,
|
||
content = _e.content;
|
||
var getTitle = this.get('getTitle');
|
||
var getContent = this.get('getContent');
|
||
var getContentPlaceholder = this.get('getContentPlaceholder') || function () {
|
||
return '';
|
||
};
|
||
var getTitlePlaceHolder = this.get('getTitlePlaceHolder') || function () {
|
||
return '';
|
||
};
|
||
var contentPlaceholder = getContentPlaceholder(item);
|
||
var titlePlaceholder = getTitlePlaceHolder(item);
|
||
var newCard = createDom(this.getDOMContent(__assign({
|
||
itemId: itemId,
|
||
collapsed: collapsed,
|
||
title: ((_b = title || propsTitle || (getTitle === null || getTitle === void 0 ? void 0 : getTitle(item))) === null || _b === void 0 ? void 0 : _b.substr(0, maxTitleLength)) || titlePlaceholder,
|
||
content: content || propsContent || (getContent === null || getContent === void 0 ? void 0 : getContent(item)) || contentPlaceholder
|
||
}, otherCardCfg)));
|
||
var minHeightPx = isNumber(minHeight) ? "".concat(minHeight, "px") : minHeight;
|
||
modifyCSS(newCard, {
|
||
minHeight: collapsed ? 'unset' : minHeightPx,
|
||
minWidth: isNumber(minWidth) ? "".concat(minWidth, "px") : minWidth,
|
||
height: height,
|
||
width: width
|
||
});
|
||
var exist = !!card;
|
||
if (exist) {
|
||
// 移除相应连线
|
||
link === null || link === void 0 ? void 0 : link.remove(true);
|
||
// 替换原来的卡片
|
||
container.replaceChild(newCard, card);
|
||
} else {
|
||
container.appendChild(newCard);
|
||
}
|
||
var containerBBox;
|
||
if (!containerCfg) {
|
||
containerBBox = container.getBoundingClientRect() || {};
|
||
if (propsX !== undefined && propsY !== undefined) {
|
||
// 使用配置的位置
|
||
x = propsX;
|
||
y = propsY;
|
||
} else if (!exist && !isCanvas) {
|
||
// 第一次创建,且无 conatiner,初始化位置
|
||
var containerTop = containerBBox.top;
|
||
var _f = defaultBegin || {},
|
||
beginLeft = _f.left,
|
||
_g = _f.right,
|
||
propsBeginRight = _g === void 0 ? 16 : _g,
|
||
_h = _f.top,
|
||
propsBeginTop = _h === void 0 ? 8 : _h,
|
||
beginBottom = _f.bottom;
|
||
var beginRight = propsBeginRight;
|
||
var beginTop = propsBeginTop;
|
||
if (!isNaN(beginLeft)) {
|
||
beginRight = container.scrollWidth - beginLeft;
|
||
}
|
||
if (!isNaN(beginBottom)) {
|
||
beginTop = container.scrollHeight - beginBottom;
|
||
}
|
||
var cardWidth = isNumber(minWidth) ? minWidth : 100;
|
||
x = container.scrollWidth - newCard.scrollWidth - (rows.length - 1) * cardWidth - beginRight;
|
||
var currentRow = rows[rows.length - 1];
|
||
var lastCardBBox = (currentRow[currentRow.length - 1] || {}).bbox;
|
||
y = (lastCardBBox === null || lastCardBBox === void 0 ? void 0 : lastCardBBox.bottom) - containerTop || beginTop;
|
||
}
|
||
modifyCSS(newCard, {
|
||
position: 'absolute',
|
||
left: "".concat(x, "px"),
|
||
top: "".concat(y, "px"),
|
||
cusor: containerCfg ? 'unset' : 'move'
|
||
});
|
||
}
|
||
this.bindListener(newCard, itemId);
|
||
var cardBBox = newCard.getBoundingClientRect();
|
||
if (!isCanvas) {
|
||
// 创建相关连线
|
||
var path = getPathItem2Card(item, cardBBox, graph, this.get('canvas'));
|
||
var linkStyle = this.get('linkStyle');
|
||
link = linkGroup.addShape('path', {
|
||
attrs: __assign({
|
||
lineWidth: 1,
|
||
lineDash: [5, 5],
|
||
stroke: '#ccc',
|
||
path: path
|
||
}, linkStyle)
|
||
});
|
||
}
|
||
cardInfoMap[itemId] = __assign(__assign({}, cardInfoMap[itemId] || {}), {
|
||
id: itemId,
|
||
collapsed: collapsed,
|
||
card: newCard,
|
||
link: link,
|
||
x: x,
|
||
y: y,
|
||
cardBBox: cardBBox,
|
||
content: content || propsContent,
|
||
title: title || propsTitle,
|
||
contentPlaceholder: contentPlaceholder,
|
||
titlePlaceholder: titlePlaceholder,
|
||
isCanvas: isCanvas
|
||
});
|
||
self.set('cardInfoMap', cardInfoMap);
|
||
if (containerCfg) {
|
||
this.updateCardPositionsInConatainer();
|
||
this.updateLinks();
|
||
} else {
|
||
var hasPropsPosition = !isNaN(propsX) && !isNaN(propsY);
|
||
if (!exist && !isCanvas && !hasPropsPosition) {
|
||
// 没有 container、新增 card 时,记录当前列中最下方位置,方便换行
|
||
var _j = containerBBox.bottom,
|
||
containerBottom = _j === void 0 ? 0 : _j,
|
||
containerTop = containerBBox.top;
|
||
rows[rows.length - 1].push({
|
||
id: itemId,
|
||
bbox: cardBBox
|
||
});
|
||
if (cardBBox.top > containerBottom - containerTop - cardBBox.height - 16) rows.push([]);
|
||
this.set('rows', rows);
|
||
}
|
||
}
|
||
this.updateCardSize(itemId);
|
||
var onAnnotationChange = this.get('onAnnotationChange');
|
||
onAnnotationChange === null || onAnnotationChange === void 0 ? void 0 : onAnnotationChange(cardInfoMap[itemId], exist ? 'update' : 'create');
|
||
};
|
||
Annotation.prototype.updateCardPositionsInConatainer = function () {
|
||
if (this.destroyed) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var container = this.get('container');
|
||
var position = this.get('containerCfg').position;
|
||
var containerWidth = container.getBoundingClientRect().width;
|
||
var computeStyle = getComputedStyle(container);
|
||
var sidePadding = px2Num(computeStyle['paddingLeft']) + px2Num(computeStyle['paddingRight']);
|
||
containerWidth -= sidePadding;
|
||
Object.values(cardInfoMap).forEach(function (_a) {
|
||
var card = _a.card;
|
||
var cardWidth = card.getBoundingClientRect().width;
|
||
switch (position) {
|
||
case 'right':
|
||
modifyCSS(card, {
|
||
marginLeft: containerWidth ? "".concat(containerWidth - cardWidth, "px") : '0px'
|
||
});
|
||
break;
|
||
case 'top':
|
||
case 'bottom':
|
||
modifyCSS(card, {
|
||
marginLeft: '8px'
|
||
});
|
||
default:
|
||
break;
|
||
}
|
||
});
|
||
};
|
||
Annotation.prototype.handleExpandCollapseCard = function (id) {
|
||
if (this.destroyed) return;
|
||
var graph = this.get('graph');
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var collapsed = cardInfoMap[id].collapsed;
|
||
var item = graph.findById(id);
|
||
if (!item) return;
|
||
var collapseType = this.get('cardCfg').collapseType;
|
||
if (collapseType === 'hide' && !collapsed) {
|
||
// collapse 行为被配置为隐藏
|
||
this.hideCard(id);
|
||
} else {
|
||
this.toggleAnnotation(item, {
|
||
collapsed: !collapsed
|
||
});
|
||
}
|
||
cardInfoMap[id] = __assign(__assign({}, cardInfoMap[id]), {
|
||
collapsed: !collapsed
|
||
});
|
||
};
|
||
/**
|
||
* 隐藏标注卡片,下次打开还保留隐藏前的配置,包括文本内容、位置等
|
||
* @param id 卡片 id,即元素(节点/边)的 id
|
||
* @returns
|
||
*/
|
||
Annotation.prototype.hideCard = function (id) {
|
||
if (this.destroyed) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap || !cardInfoMap[id]) return;
|
||
var _a = cardInfoMap[id],
|
||
card = _a.card,
|
||
link = _a.link;
|
||
modifyCSS(card, {
|
||
display: 'none'
|
||
});
|
||
link === null || link === void 0 ? void 0 : link.hide();
|
||
var onAnnotationChange = this.get('onAnnotationChange');
|
||
onAnnotationChange(cardInfoMap[id], 'hide');
|
||
};
|
||
/**
|
||
* 移除标注卡片,下一次生成时将被初始化
|
||
* @param id 卡片 id,即元素(节点/边)的 id
|
||
* @returns
|
||
*/
|
||
Annotation.prototype.removeCard = function (id) {
|
||
if (this.destroyed) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var cardInfo = cardInfoMap[id];
|
||
var card = cardInfo.card,
|
||
link = cardInfo.link;
|
||
var container = this.get('container');
|
||
container.removeChild(card);
|
||
link === null || link === void 0 ? void 0 : link.remove(true);
|
||
delete cardInfoMap[id];
|
||
var onAnnotationChange = this.get('onAnnotationChange');
|
||
onAnnotationChange(cardInfo, 'remove');
|
||
};
|
||
Annotation.prototype.bindListener = function (card, itemId) {
|
||
var _this = this;
|
||
if (this.destroyed) return;
|
||
card.addEventListener('mousemove', function (e) {
|
||
// icon 的鼠标进入监听,方便外部加 tooltip
|
||
var iconType;
|
||
if (e.target.className === 'g6-annotation-collapse') {
|
||
iconType = 'collapse';
|
||
} else if (e.target.className === 'g6-annotation-expand') {
|
||
iconType = 'expand';
|
||
} else if (e.target.className === 'g6-annotation-close') {
|
||
iconType = 'close';
|
||
}
|
||
if (iconType) {
|
||
var _a = _this.get('cardCfg').onMouseEnterIcon,
|
||
onMouseEnterIcon = _a === void 0 ? function () {} : _a;
|
||
onMouseEnterIcon(e, itemId, iconType);
|
||
}
|
||
});
|
||
card.addEventListener('mouseout', function (e) {
|
||
// icon 的鼠标移出监听,方便外部加 tooltip
|
||
var iconType;
|
||
if (e.target.className === 'g6-annotation-collapse') {
|
||
iconType = 'collapse';
|
||
} else if (e.target.className === 'g6-annotation-expand') {
|
||
iconType = 'expand';
|
||
} else if (e.target.className === 'g6-annotation-close') {
|
||
iconType = 'close';
|
||
}
|
||
if (iconType) {
|
||
var _a = _this.get('cardCfg').onMouseLeaveIcon,
|
||
onMouseLeaveIcon = _a === void 0 ? function () {} : _a;
|
||
onMouseLeaveIcon(e, itemId, iconType);
|
||
}
|
||
});
|
||
// mouseenter and mouseleave to highlight the corresponding items
|
||
card.addEventListener('mouseenter', function (e) {
|
||
var cardInfoMap = _this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var graph = _this.get('graph');
|
||
var item = graph.findById(itemId);
|
||
if (item) {
|
||
var itemHighlightState = _this.get('itemHighlightState');
|
||
graph.setItemState(item, itemHighlightState, true);
|
||
}
|
||
var link = cardInfoMap[itemId].link;
|
||
if (link) {
|
||
var linkHighlightStyle = _this.get('linkHighlightStyle') || {};
|
||
link.attr(linkHighlightStyle);
|
||
}
|
||
});
|
||
card.addEventListener('mouseleave', function (e) {
|
||
var cardInfoMap = _this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var graph = _this.get('graph');
|
||
var item = graph.findById(itemId);
|
||
if (item) {
|
||
var itemHighlightState = _this.get('itemHighlightState');
|
||
graph.setItemState(item, itemHighlightState, false);
|
||
}
|
||
var link = cardInfoMap[itemId].link;
|
||
if (link) {
|
||
var linkHighlightStyle = _this.get('linkHighlightStyle') || {};
|
||
Object.keys(linkHighlightStyle).forEach(function (key) {
|
||
link.attr(key, undefined);
|
||
link.attr(key, undefined);
|
||
});
|
||
var linkStyle = _this.get('linkStyle');
|
||
link.attr(linkStyle);
|
||
}
|
||
});
|
||
card.addEventListener('click', function (e) {
|
||
var onClickIcon = (_this.get('cardCfg') || {}).onClickIcon;
|
||
if (e.target.className === 'g6-annotation-collapse' || e.target.className === 'g6-annotation-expand') {
|
||
// collapse & expand
|
||
var collapseType = _this.get('cardCfg').collapseType;
|
||
if (collapseType === 'hide') {
|
||
_this.hideCard(itemId);
|
||
} else {
|
||
_this.handleExpandCollapseCard(itemId);
|
||
}
|
||
onClickIcon === null || onClickIcon === void 0 ? void 0 : onClickIcon(e, itemId, e.target.className === 'g6-annotation-collapse' ? 'collapse' : 'expand');
|
||
} else if (e.target.className === 'g6-annotation-close') {
|
||
// close
|
||
var closeType = _this.get('cardCfg').closeType;
|
||
if (closeType === 'remove') {
|
||
_this.removeCard(itemId);
|
||
} else {
|
||
_this.hideCard(itemId);
|
||
}
|
||
onClickIcon === null || onClickIcon === void 0 ? void 0 : onClickIcon(e, itemId, 'close');
|
||
}
|
||
});
|
||
// dblclick to edit the title and content text
|
||
var editable = this.get('editable');
|
||
if (editable) {
|
||
card.addEventListener('dblclick', function (e) {
|
||
var cardInfoMap = _this.get('cardInfoMap');
|
||
var _a = (_this.get('cardCfg') || {}).maxTitleLength,
|
||
maxTitleLength = _a === void 0 ? 20 : _a;
|
||
if (!cardInfoMap) return;
|
||
var target = e.target;
|
||
var targetClass = target.className;
|
||
if (targetClass !== 'g6-annotation-title' && targetClass !== 'g6-annotation-content') return;
|
||
var _b = targetClass === 'g6-annotation-title' ? target.getBoundingClientRect() : target.parentNode.getBoundingClientRect(),
|
||
width = _b.width,
|
||
height = _b.height;
|
||
var computeStyle = getComputedStyle(target);
|
||
var inputTag = targetClass === 'g6-annotation-title' ? 'input' : 'textarea';
|
||
var input = createDom("<".concat(inputTag, " class=\"").concat(targetClass, "-input\" type=\"textarea\" style=\"width:").concat(width, "px; height: ").concat(height, "px; min-width: 16px;\"/>"));
|
||
var inputWrapper = createDom("<div class=\"".concat(targetClass, "-input-wrapper\" style=\"width: ").concat(width, "px; height: ").concat(height, "px; min-width: 16px; margin-right: ").concat(computeStyle['marginRight'], "\" />"));
|
||
inputWrapper.appendChild(input);
|
||
target.parentNode.replaceChild(inputWrapper, target);
|
||
var cardInfo = cardInfoMap[itemId];
|
||
var contentPlaceholder = cardInfo.contentPlaceholder,
|
||
titlePlaceholder = cardInfo.titlePlaceholder,
|
||
content = cardInfo.content,
|
||
title = cardInfo.title;
|
||
var value = content;
|
||
if (targetClass === 'g6-annotation-title') {
|
||
input.name = 'title';
|
||
input.maxLength = maxTitleLength;
|
||
value = title;
|
||
} else {
|
||
input.name = 'content';
|
||
}
|
||
if (value) {
|
||
input.innerHTML = target.innerHTML;
|
||
input.value = target.innerHTML;
|
||
} else {
|
||
input.placeholder = targetClass === 'g6-annotation-title' ? titlePlaceholder : contentPlaceholder;
|
||
}
|
||
input.focus();
|
||
input.addEventListener('blur', function (blurEvt) {
|
||
if (input.value) {
|
||
target.innerHTML = input.value;
|
||
cardInfo[input.name || 'title'] = input.value;
|
||
}
|
||
inputWrapper.parentNode.replaceChild(target, inputWrapper);
|
||
_this.updateCardSize(itemId);
|
||
var onAnnotationChange = _this.get('onAnnotationChange');
|
||
onAnnotationChange === null || onAnnotationChange === void 0 ? void 0 : onAnnotationChange(cardInfo, 'update');
|
||
});
|
||
});
|
||
}
|
||
var unmovableClasses = ['g6-annotation-title', 'g6-annotation-content', 'g6-annotation-title-input', 'g6-annotation-content-input'];
|
||
card.draggable = true;
|
||
card.addEventListener('dragstart', function (e) {
|
||
var targetClass = e.target.className;
|
||
if (unmovableClasses.includes(targetClass)) return;
|
||
var style = card.style;
|
||
_this.set('dragging', {
|
||
card: card,
|
||
x: e.clientX,
|
||
y: e.clientY,
|
||
left: px2Num(style.left),
|
||
top: px2Num(style.top)
|
||
});
|
||
});
|
||
card.addEventListener('drag', function (e) {
|
||
e.preventDefault();
|
||
var cardInfoMap = _this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var clientX = e.clientX,
|
||
clientY = e.clientY;
|
||
var dragging = _this.get('dragging');
|
||
if (isNaN(clientX) || isNaN(clientY) || !dragging) return;
|
||
var x = dragging.x,
|
||
y = dragging.y,
|
||
left = dragging.left,
|
||
top = dragging.top,
|
||
draggingCard = dragging.card;
|
||
var dx = clientX - x;
|
||
var dy = clientY - y;
|
||
left += dx;
|
||
top += dy;
|
||
var graph = _this.get('graph');
|
||
var graphLeftTopCanvas = graph.getPointByCanvas(0, 0);
|
||
var graphRightBottomCanvas = graph.getPointByCanvas(graph.getWidth(), graph.getHeight());
|
||
var _a = graph.getClientByPoint(graphLeftTopCanvas.x, graphLeftTopCanvas.y),
|
||
graphLeft = _a.x,
|
||
graphTop = _a.y;
|
||
var _b = graph.getClientByPoint(graphRightBottomCanvas.x, graphRightBottomCanvas.y),
|
||
graphRight = _b.x,
|
||
graphBottom = _b.y;
|
||
var cardBBox = draggingCard.getBoundingClientRect();
|
||
var cardWidth = cardBBox.right - cardBBox.left;
|
||
var cardHeight = cardBBox.bottom - cardBBox.top;
|
||
if (left > graphRight - graphLeft - cardWidth && dx > 0 || left < 0 && dx < 0) left -= dx;
|
||
if (top > graphBottom - graphTop - cardHeight && dy > 0 || top < 0 && dy < 0) top -= dy;
|
||
// 更新卡片位置
|
||
modifyCSS(draggingCard, {
|
||
left: "".concat(left, "px"),
|
||
top: "".concat(top, "px"),
|
||
visibility: 'hidden'
|
||
});
|
||
x = clientX;
|
||
y = clientY;
|
||
// 更新连线位置
|
||
var link = (cardInfoMap[itemId] || {}).link;
|
||
if (link) {
|
||
var item = graph.findById(itemId);
|
||
link.attr('path', getPathItem2Card(item, cardBBox, graph, _this.get('canvas')));
|
||
}
|
||
_this.set('dragging', {
|
||
x: x,
|
||
y: y,
|
||
left: left,
|
||
top: top,
|
||
card: draggingCard
|
||
});
|
||
});
|
||
var dragendListener = function dragendListener(e) {
|
||
var cardInfoMap = _this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var dragging = _this.get('dragging');
|
||
if (dragging) {
|
||
// = dragend
|
||
var left = dragging.left,
|
||
top_1 = dragging.top,
|
||
draggingCard = dragging.card;
|
||
cardInfoMap[itemId].x = left;
|
||
cardInfoMap[itemId].y = top_1;
|
||
modifyCSS(draggingCard, {
|
||
visibility: 'visible'
|
||
});
|
||
_this.set('dragging', false);
|
||
// 移动过的卡片从 rows 中移除,避免影响后续卡片出生位置
|
||
var rows = _this.get("rows");
|
||
rows === null || rows === void 0 ? void 0 : rows.forEach(function (rowItems) {
|
||
for (var i = rowItems.length - 1; i >= 0; i--) {
|
||
if (rowItems[i].id === itemId) rowItems.splice(i, 1);
|
||
}
|
||
});
|
||
var onAnnotationChange = _this.get('onAnnotationChange');
|
||
onAnnotationChange === null || onAnnotationChange === void 0 ? void 0 : onAnnotationChange(cardInfoMap[itemId], 'update');
|
||
}
|
||
};
|
||
card.addEventListener('dragend', dragendListener);
|
||
};
|
||
Annotation.prototype.updateCardSize = function (id) {
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var card = cardInfoMap[id].card;
|
||
var width = card.getBoundingClientRect().width;
|
||
var title = card.getElementsByClassName('g6-annotation-title')[0];
|
||
if (title) {
|
||
var computeStyle = getComputedStyle(title);
|
||
var sideMargin = px2Num(computeStyle['marginLeft']);
|
||
var titleWidth = title.getBoundingClientRect().width;
|
||
modifyCSS(title, {
|
||
marginRight: "".concat(width - sideMargin - 24 - 16 - titleWidth, "px")
|
||
});
|
||
}
|
||
};
|
||
Annotation.prototype.updateLink = function (_a) {
|
||
var item = _a.item;
|
||
if (!item) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var canvas = this.get('canvas');
|
||
var graph = this.get('graph');
|
||
var id = item.getID();
|
||
var _b = cardInfoMap[id] || {},
|
||
link = _b.link,
|
||
card = _b.card;
|
||
if (link) {
|
||
var path = getPathItem2Card(item, card.getBoundingClientRect(), graph, canvas);
|
||
link.attr('path', path);
|
||
}
|
||
};
|
||
Annotation.prototype.updateLinks = function () {
|
||
var _this = this;
|
||
if (this.destroyed) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var graph = this.get('graph');
|
||
Object.values(cardInfoMap).forEach(function (cardInfo) {
|
||
var id = cardInfo.id;
|
||
var item = graph.findById(id);
|
||
_this.updateLink({
|
||
item: item
|
||
});
|
||
});
|
||
};
|
||
Annotation.prototype.onGraphDataChange = function () {
|
||
var _this = this;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var graph = this.get('graph');
|
||
Object.values(cardInfoMap).forEach(function (info) {
|
||
var id = info.id,
|
||
card = info.card,
|
||
isCanvas = info.isCanvas;
|
||
if (!card || isCanvas || card.style.display === 'none') return;
|
||
var item = graph.findById(id);
|
||
if (item && item.isVisible()) {
|
||
_this.toggleAnnotation(item);
|
||
} else {
|
||
_this.hideCard(id);
|
||
}
|
||
});
|
||
};
|
||
Annotation.prototype.onGraphItemVisibilityChange = function (_a) {
|
||
var item = _a.item,
|
||
visible = _a.visible;
|
||
if (!item || item.destroyed) return;
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var id = item.getID();
|
||
if (!cardInfoMap[id]) return;
|
||
if (!visible) this.hideCard(id);
|
||
};
|
||
Annotation.prototype.saveData = function (saveClosed) {
|
||
if (saveClosed === void 0) {
|
||
saveClosed = false;
|
||
}
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var graph = this.get('graph');
|
||
var getTitle = this.get('getTitle');
|
||
var getContent = this.get('getContent');
|
||
var data = [];
|
||
Object.values(cardInfoMap).forEach(function (info) {
|
||
var title = info.title,
|
||
content = info.content,
|
||
x = info.x,
|
||
y = info.y,
|
||
id = info.id,
|
||
collapsed = info.collapsed,
|
||
card = info.card;
|
||
if (card && card.style.display === 'none' && !saveClosed) return;
|
||
var item = graph.findById(id) || graph.get('canvas');
|
||
data.push({
|
||
id: id,
|
||
x: x,
|
||
y: y,
|
||
collapsed: collapsed,
|
||
title: title || (getTitle === null || getTitle === void 0 ? void 0 : getTitle(item)),
|
||
content: content || (getContent === null || getContent === void 0 ? void 0 : getContent(item)),
|
||
visible: card && card.style.display !== 'none'
|
||
});
|
||
});
|
||
return data;
|
||
};
|
||
Annotation.prototype.readData = function (data) {
|
||
var _this = this;
|
||
var graph = this.get('graph');
|
||
data.forEach(function (info) {
|
||
var id = info.id,
|
||
x = info.x,
|
||
y = info.y,
|
||
title = info.title,
|
||
content = info.content,
|
||
collapsed = info.collapsed,
|
||
visible = info.visible;
|
||
var item = graph.findById(id);
|
||
if (!item && id === CANVAS_ANNOTATION_ID) {
|
||
item = graph.get('canvas');
|
||
}
|
||
if (!item) {
|
||
var cardInfoMap = _this.get('cardInfoMap') || {};
|
||
cardInfoMap[id] = info;
|
||
_this.set('cardInfoMap', cardInfoMap);
|
||
return;
|
||
}
|
||
_this.toggleAnnotation(item, {
|
||
x: x,
|
||
y: y,
|
||
title: title,
|
||
content: content,
|
||
collapsed: collapsed
|
||
});
|
||
if (!visible) _this.hideCard(id);
|
||
});
|
||
};
|
||
/**
|
||
* Clear the cards and links
|
||
*/
|
||
Annotation.prototype.clear = function () {
|
||
var cardInfoMap = this.get('cardInfoMap');
|
||
if (!cardInfoMap) return;
|
||
var container = this.get('container');
|
||
Object.values(cardInfoMap).forEach(function (cardInfo) {
|
||
var card = cardInfo.card,
|
||
link = cardInfo.link;
|
||
container.removeChild(card);
|
||
link === null || link === void 0 ? void 0 : link.remove(true);
|
||
});
|
||
this.set('cardInfoMap', {});
|
||
};
|
||
/**
|
||
* Destroy the component
|
||
*/
|
||
Annotation.prototype.destroy = function () {
|
||
var _a;
|
||
this.clear();
|
||
(_a = this.get('canvas')) === null || _a === void 0 ? void 0 : _a.destroy();
|
||
var graph = this.get('graph');
|
||
if (!graph || graph.destroyed) return;
|
||
if (this.get('containerCfg')) {
|
||
graph.getContainer().removeChild(this.get('container'));
|
||
}
|
||
this.destroyed = true;
|
||
};
|
||
return Annotation;
|
||
}(Base);
|
||
export default Annotation;
|
||
var getPath = function getPath(startPoints, endPoints) {
|
||
var startPoint,
|
||
endPoint,
|
||
posKeys,
|
||
distance = Infinity;
|
||
Object.keys(startPoints).forEach(function (skey) {
|
||
var spos = startPoints[skey];
|
||
Object.keys(endPoints).forEach(function (ekey) {
|
||
var epos = endPoints[ekey];
|
||
var xdist = spos.x - epos.x;
|
||
var ydist = spos.y - epos.y;
|
||
var dist = xdist * xdist + ydist * ydist;
|
||
if (distance > dist) {
|
||
distance = dist;
|
||
startPoint = spos;
|
||
endPoint = epos;
|
||
posKeys = [skey, ekey];
|
||
}
|
||
});
|
||
});
|
||
var curveOffset = 20;
|
||
var controlPoint = Util.getControlPoint(startPoint, endPoint, 0.5, curveOffset);
|
||
return [['M', startPoint.x, startPoint.y], ['Q', controlPoint.x, controlPoint.y, endPoint.x, endPoint.y]];
|
||
};
|
||
var getPathItem2Card = function getPathItem2Card(item, cardBBox, graph, annotationCanvas) {
|
||
var _a;
|
||
var itemLinkPoints;
|
||
var itemType = item.getType();
|
||
if (itemType === 'edge') {
|
||
itemLinkPoints = [item.getKeyShape().getPoint(0.5)];
|
||
} else {
|
||
var _b = (_a = item.getKeyShape) === null || _a === void 0 ? void 0 : _a.call(item).getBBox(),
|
||
minX = _b.minX,
|
||
minY = _b.minY,
|
||
maxX = _b.maxX,
|
||
maxY = _b.maxY;
|
||
var _c = item.getModel(),
|
||
x = _c.x,
|
||
y = _c.y;
|
||
minX += x;
|
||
minY += y;
|
||
maxX += x;
|
||
maxY += y;
|
||
itemLinkPoints = {
|
||
left: {
|
||
x: minX,
|
||
y: (minY + maxY) / 2
|
||
},
|
||
right: {
|
||
x: maxX,
|
||
y: (minY + maxY) / 2
|
||
},
|
||
top: {
|
||
x: (minX + maxX) / 2,
|
||
y: minY
|
||
},
|
||
bottom: {
|
||
x: (minX + maxX) / 2,
|
||
y: maxY
|
||
}
|
||
};
|
||
}
|
||
// 由 graph 所在 canvas 转换为 Client 坐标系,然后再由 annotation 所在 canvas 转换为绘制坐标系
|
||
Object.keys(itemLinkPoints).forEach(function (key) {
|
||
var _a = itemLinkPoints[key],
|
||
x = _a.x,
|
||
y = _a.y;
|
||
var clientPos = graph.getClientByPoint(x, y);
|
||
itemLinkPoints[key] = annotationCanvas.getPointByClient(clientPos.x, clientPos.y);
|
||
});
|
||
var _d = cardBBox.top,
|
||
cardTop = _d === void 0 ? 0 : _d,
|
||
_e = cardBBox.left,
|
||
cardLeft = _e === void 0 ? 0 : _e,
|
||
_f = cardBBox.right,
|
||
cardRight = _f === void 0 ? 0 : _f,
|
||
_g = cardBBox.bottom,
|
||
cardBottom = _g === void 0 ? 0 : _g;
|
||
var cardLinkPoints = {
|
||
left: annotationCanvas.getPointByClient(cardLeft, (cardTop + cardBottom) / 2),
|
||
right: annotationCanvas.getPointByClient(cardRight, (cardTop + cardBottom) / 2),
|
||
top: annotationCanvas.getPointByClient((cardLeft + cardRight) / 2, cardTop),
|
||
bottom: annotationCanvas.getPointByClient((cardLeft + cardRight) / 2, cardBottom)
|
||
};
|
||
return getPath(itemLinkPoints, cardLinkPoints);
|
||
};
|
||
var px2Num = function px2Num(px) {
|
||
return Number(px.replace(/\s+|px/gi, "")) || 0;
|
||
}; |