@logicflow/core
Version:
LogicFlow, help you quickly create flowcharts
329 lines (328 loc) • 15.9 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (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 __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
import { Component } from 'preact/compat';
import { Circle, Line } from './shape';
import { ElementState, EventType } from '../constant';
import { StepDrag, formatAnchorConnectValidateData, targetNodeInfo, distance, cancelRaf, createRaf, } from '../util';
var Anchor = /** @class */ (function (_super) {
__extends(Anchor, _super);
function Anchor() {
var _this = _super.call(this) || this;
// TODO: 确定 event 是否会有 null 和 undefined 的情况,事件类型做相应的适配
_this.onDragStart = function (_a) {
var event = _a.event;
var _b = _this.props, anchorData = _b.anchorData, nodeModel = _b.nodeModel, graphModel = _b.graphModel;
graphModel.selectNodeById(nodeModel.id);
if (nodeModel.autoToFront) {
graphModel.toFront(nodeModel.id);
}
graphModel.eventCenter.emit(EventType.ANCHOR_DRAGSTART, {
data: anchorData,
e: event,
nodeModel: nodeModel,
});
_this.setState({
startX: anchorData.x,
startY: anchorData.y,
endX: anchorData.x,
endY: anchorData.y,
});
};
_this.onDragging = function (_a) {
var event = _a.event;
var _b = _this.props, graphModel = _b.graphModel, nodeModel = _b.nodeModel, anchorData = _b.anchorData;
var transformModel = graphModel.transformModel, eventCenter = graphModel.eventCenter, width = graphModel.width, height = graphModel.height, _c = graphModel.editConfigModel, autoExpand = _c.autoExpand, stopMoveGraph = _c.stopMoveGraph;
// TODO:确认该方法是否有影响!理论上 onDragging 时 event 必有值
if (!event)
return;
var clientX = event.clientX, clientY = event.clientY;
var _d = graphModel.getPointByClient({
x: clientX,
y: clientY,
}), _e = _d.domOverlayPosition, x = _e.x, y = _e.y, _f = _d.canvasOverlayPosition, x1 = _f.x, y1 = _f.y;
if (_this.t) {
cancelRaf(_this.t);
}
var nearBoundary = []; // TODO: 定义元组类型 Tuple
var size = 10;
if (x < 10) {
nearBoundary = [size, 0];
}
else if (x + 10 > width) {
nearBoundary = [-size, 0];
}
else if (y < 10) {
nearBoundary = [0, size];
}
else if (y + 10 > height) {
nearBoundary = [0, -size];
}
_this.setState({
endX: x1,
endY: y1,
dragging: true,
});
_this.moveAnchorEnd(x1, y1);
if (nearBoundary.length > 0 && !stopMoveGraph && autoExpand) {
_this.t = createRaf(function () {
var _a = __read(nearBoundary, 2), translateX = _a[0], translateY = _a[1];
transformModel.translate(translateX, translateY);
var _b = _this.state, endX = _b.endX, endY = _b.endY;
_this.setState({
endX: endX - translateX,
endY: endY - translateY,
});
_this.moveAnchorEnd(endX - translateX, endY - translateY);
});
}
eventCenter.emit(EventType.ANCHOR_DRAG, {
data: anchorData,
e: event,
nodeModel: nodeModel,
});
};
_this.onDragEnd = function (_a) {
var event = _a.event;
if (_this.t) {
cancelRaf(_this.t);
}
var edgeModel = _this.checkEnd(event);
_this.setState({
startX: 0,
startY: 0,
endX: 0,
endY: 0,
dragging: false,
});
// 清除掉缓存结果 fix:#320 因为创建边之后,会影响校验结果变化,所以需要重新校验
_this.sourceRuleResults.clear();
_this.targetRuleResults.clear();
var _b = _this.props, graphModel = _b.graphModel, nodeModel = _b.nodeModel, anchorData = _b.anchorData;
graphModel.eventCenter.emit(EventType.ANCHOR_DRAGEND, {
data: anchorData,
e: event,
nodeModel: nodeModel,
edgeModel: edgeModel !== null && edgeModel !== void 0 ? edgeModel : undefined,
});
};
_this.checkEnd = function (event) {
var _a;
var _b = _this.props, graphModel = _b.graphModel, nodeModel = _b.nodeModel, _c = _b.anchorData, x = _c.x, y = _c.y, id = _c.id;
// nodeModel.setSelected(false);
/* 创建边 */
var _d = _this.state, endX = _d.endX, endY = _d.endY, dragging = _d.dragging;
var info = targetNodeInfo({
x: endX,
y: endY,
}, graphModel);
// 为了保证鼠标离开的时候,将上一个节点状态重置为正常状态。
if (_this.preTargetNode &&
_this.preTargetNode.state !== ElementState.DEFAULT) {
_this.preTargetNode.setElementState(ElementState.DEFAULT);
}
// 没有dragging就结束边
if (!dragging)
return;
if (info && info.node) {
var targetNode = info.node;
var anchorId = info.anchor.id;
var targetInfoId = "".concat(nodeModel.id, "_").concat(targetNode.id, "_").concat(anchorId, "_").concat(id);
var _e = _this.sourceRuleResults.get(targetInfoId) || {}, isSourcePass = _e.isAllPass, sourceMsg = _e.msg;
var _f = _this.targetRuleResults.get(targetInfoId) || {}, isTargetPass = _f.isAllPass, targetMsg = _f.msg;
if (isSourcePass && isTargetPass) {
targetNode.setElementState(ElementState.DEFAULT);
var targetNodeModel = graphModel.getNodeModelById(info.node.id);
var edgeData = (_a = graphModel.edgeGenerator) === null || _a === void 0 ? void 0 : _a.call(graphModel, nodeModel.getData(), targetNodeModel === null || targetNodeModel === void 0 ? void 0 : targetNodeModel.getData());
var edgeModel = graphModel.addEdge(__assign(__assign({}, edgeData), { sourceNodeId: nodeModel.id, sourceAnchorId: id, startPoint: {
x: x,
y: y,
}, targetNodeId: info.node.id, targetAnchorId: info.anchor.id, endPoint: {
x: info.anchor.x,
y: info.anchor.y,
} }));
var anchorData = _this.props.anchorData;
graphModel.eventCenter.emit(EventType.ANCHOR_DROP, {
data: anchorData,
e: event,
nodeModel: nodeModel,
edgeModel: edgeModel,
});
return edgeModel;
}
var nodeData = targetNode.getData();
graphModel.eventCenter.emit(EventType.CONNECTION_NOT_ALLOWED, {
data: nodeData,
msg: targetMsg || sourceMsg || '不允许添加连线',
});
return null;
}
};
_this.sourceRuleResults = new Map();
_this.targetRuleResults = new Map();
_this.state = {
startX: 0,
startY: 0,
endX: 0,
endY: 0,
dragging: false,
};
_this.dragHandler = new StepDrag({
onDragStart: _this.onDragStart,
onDragging: _this.onDragging,
onDragEnd: _this.onDragEnd,
});
return _this;
}
Anchor.prototype.getAnchorShape = function () {
var _a = this.props, anchorData = _a.anchorData, style = _a.style, node = _a.node;
var anchorShape = node.getAnchorShape(anchorData);
if (anchorShape)
return anchorShape;
var x = anchorData.x, y = anchorData.y;
var hoverStyle = __assign(__assign({}, style), style === null || style === void 0 ? void 0 : style.hover);
return (_jsxs("g", { children: [_jsx(Circle, __assign({ className: "lf-node-anchor-hover" }, hoverStyle, { x: x, y: y })), _jsx(Circle, __assign({ className: "lf-node-anchor" }, style, { x: x, y: y }))] }));
};
Object.defineProperty(Anchor.prototype, "customTrajectory", {
get: function () {
var customTrajectory = this.props.graphModel.customTrajectory;
return customTrajectory;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Anchor.prototype, "relateEdges", {
get: function () {
var _a = this.props, _b = _a.graphModel, getAnchorIncomingEdge = _b.getAnchorIncomingEdge, getAnchorOutgoingEdge = _b.getAnchorOutgoingEdge, id = _a.anchorData.id;
return {
incomingEdgeList: getAnchorIncomingEdge(id),
outgoingEdgeList: getAnchorOutgoingEdge(id),
};
},
enumerable: false,
configurable: true
});
Anchor.prototype.moveAnchorEnd = function (endX, endY) {
var _a, _b;
var _c = this.props, graphModel = _c.graphModel, nodeModel = _c.nodeModel, anchorData = _c.anchorData;
var info = targetNodeInfo({
x: endX,
y: endY,
}, graphModel);
if (info) {
var targetNode = info.node;
var anchorId = info.anchor.id;
if (this.preTargetNode && this.preTargetNode !== info.node) {
this.preTargetNode.setElementState(ElementState.DEFAULT);
}
// #500 不允许锚点自己连自己, 在锚点一开始连接的时候, 不触发自己连接自己的校验。
if (anchorData.id === anchorId) {
return;
}
this.preTargetNode = targetNode;
// 支持节点的每个锚点单独设置是否可连接,因此规则key去nodeId + anchorId作为唯一值
var targetInfoId = "".concat(nodeModel.id, "_").concat(targetNode.id, "_").concat(anchorId, "_").concat(anchorData.id);
// 查看鼠标是否进入过target,若有检验结果,表示进入过, 就不重复计算了。
if (!this.targetRuleResults.has(targetInfoId)) {
var targetAnchor = info.anchor;
var sourceRuleResult = nodeModel.isAllowConnectedAsSource(targetNode, anchorData, targetAnchor);
var targetRuleResult = targetNode.isAllowConnectedAsTarget(nodeModel, anchorData, targetAnchor);
this.sourceRuleResults.set(targetInfoId, formatAnchorConnectValidateData(sourceRuleResult));
this.targetRuleResults.set(targetInfoId, formatAnchorConnectValidateData(targetRuleResult));
}
var isSourcePass = ((_a = this.sourceRuleResults.get(targetInfoId)) !== null && _a !== void 0 ? _a : {}).isAllPass;
var isTargetPass = ((_b = this.targetRuleResults.get(targetInfoId)) !== null && _b !== void 0 ? _b : {}).isAllPass;
// 实时提示出即将链接的锚点
if (isSourcePass && isTargetPass) {
targetNode.setElementState(ElementState.ALLOW_CONNECT);
}
else {
targetNode.setElementState(ElementState.NOT_ALLOW_CONNECT);
}
}
else if (this.preTargetNode &&
this.preTargetNode.state !== ElementState.DEFAULT) {
// 为了保证鼠标离开的时候,将上一个节点状态重置为正常状态。
this.preTargetNode.setElementState(ElementState.DEFAULT);
}
};
Anchor.prototype.isShowLine = function () {
var _a = this.state, startX = _a.startX, startY = _a.startY, endX = _a.endX, endY = _a.endY;
var v = distance(startX, startY, endX, endY);
return v > 10;
};
Anchor.prototype.render = function () {
var _this = this;
var _a = this.state, startX = _a.startX, startY = _a.startY, endX = _a.endX, endY = _a.endY;
var _b = this.props, anchorData = _b.anchorData, edgeStyle = _b.edgeStyle, nodeModel = _b.nodeModel, graphModel = _b.graphModel;
var edgeAddable = anchorData.edgeAddable;
return (
// className="lf-anchor" 作为下载时,需要将锚点删除的依据,不要修改类名
_jsxs("g", { className: "lf-anchor", children: [_jsx("g", { onClick: function (ev) {
ev.stopPropagation();
graphModel.eventCenter.emit(EventType.ANCHOR_CLICK, {
data: anchorData,
e: ev,
nodeModel: nodeModel,
});
}, onMouseDown: function (ev) {
graphModel.eventCenter.emit(EventType.ANCHOR_MOUSEDOWN, {
data: anchorData,
e: ev,
nodeModel: nodeModel,
});
if (edgeAddable !== false) {
_this.dragHandler.handleMouseDown(ev);
}
}, children: this.getAnchorShape() }), this.isShowLine() &&
(this.customTrajectory ? (this.customTrajectory(__assign({ sourcePoint: {
x: startX,
y: startY,
}, targetPoint: {
x: endX,
y: endY,
} }, edgeStyle))) : (_jsx(Line, __assign({ x1: startX, y1: startY, x2: endX, y2: endY }, edgeStyle, { "pointer-events": "none" }))))] }));
};
return Anchor;
}(Component));
export default Anchor;