UNPKG

@logicflow/core

Version:

LogicFlow, help you quickly create flowcharts

1,235 lines (1,234 loc) 46.4 kB
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; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { jsx as _jsx } from "preact/jsx-runtime"; import { createElement as h, render } from 'preact/compat'; import { cloneDeep, forEach, indexOf, isNil } from 'lodash-es'; import { observer } from '.'; import { Options as LFOptions } from './options'; import * as _Model from './model'; import { GraphModel, SnaplineModel, } from './model'; import Graph from './view/Graph'; import * as _View from './view'; import { formatData, addThemeMode, removeThemeMode, clearThemeMode, } from './util'; import { Dnd, snapline } from './view/behavior'; import Tool from './tool'; import History from './history'; import Keyboard, { initDefaultShortcut } from './keyboard'; import { ElementType, EventType } from './constant'; var pluginFlag = Symbol('plugin registered by Logicflow.use'); var LogicFlow = /** @class */ (function () { function LogicFlow(options) { var _this = this; var _a; this.viewMap = new Map(); this.components = []; // 插件扩展方法 this.extension = {}; /********************************************************* * Register 相关 ********************************************************/ this.setView = function (type, component) { return _this.viewMap.set(type, component); }; // 根据 type 获取对应的 view this.getView = function (type) { return _this.viewMap.get(type); }; var initOptions = LFOptions.get(options); var container = initOptions.container, width = initOptions.width, height = initOptions.height; this.options = initOptions; this.container = this.initContainer(container, width, height); this.graphModel = new GraphModel(__assign(__assign({}, initOptions), { container: this.container })); this.plugins = (_a = initOptions.plugins) !== null && _a !== void 0 ? _a : []; var eventCenter = this.graphModel.eventCenter; this.tool = new Tool(this); this.dnd = new Dnd({ lf: this }); this.history = new History(eventCenter); this.keyboard = new Keyboard({ lf: this, keyboard: initOptions.keyboard, }); if (initOptions.snapline !== false) { this.snaplineModel = new SnaplineModel(this.graphModel, initOptions.snaplineEpsilon); snapline(eventCenter, this.snaplineModel); } if (!initOptions.isSilentMode) { // 先初始化默认内置快捷键,自定义快捷键可以覆盖默认快捷键 initDefaultShortcut(this, this.graphModel); // 然后再初始化自定义快捷键,自定义快捷键可以覆盖默认快捷键. // 插件最后初始化。方便插件强制覆盖内置快捷键 this.keyboard.initShortcuts(); } this.defaultRegister(); this.installPlugins(initOptions.disabledPlugins); } LogicFlow.prototype.initContainer = function (container, width, height) { // TODO: 确认是否需要,后续是否只要返回 container 即可(下面方法是为了解决事件绑定问题的) // fix: destroy keyboard events while destroy LogicFlow.(#1110) var lfContainer = document.createElement('div'); lfContainer.style.position = 'relative'; lfContainer.style.width = width ? "".concat(width, "px") : '100%'; lfContainer.style.height = height ? "".concat(height, "px") : '100%'; container.innerHTML = ''; container.appendChild(lfContainer); return lfContainer; }; Object.defineProperty(LogicFlow.prototype, Symbol.toStringTag, { get: function () { return LogicFlow.toStringTag; }, enumerable: false, configurable: true }); /** * 注册自定义节点和边 * 支持两种方式 * 方式一(推荐) * 详情见 todo: docs link * @example * import { RectNode, RectModel } from '@logicflow/core' * class CustomView extends RectNode { * } * class CustomModel extends RectModel { * } * lf.register({ * type: 'custom', * view: CustomView, * model: CustomModel * }) * 方式二 * 不推荐,极个别在自定义的时候需要用到lf的情况下可以用这种方式。 * 大多数情况下,我们可以直接在view中从this.props中获取graphModel * 或者model中直接this.graphModel获取model的方法。 * @example * lf.register('custom', ({ RectNode, RectModel }) => { * class CustomView extends RectNode {} * class CustomModel extends RectModel {} * return { * view: CustomView, * model: CustomModel * } * }) */ LogicFlow.prototype.register = function (element, fn, isObserverView) { if (isObserverView === void 0) { isObserverView = true; } // 方式1 if (typeof element !== 'string') { this.registerElement(element); return; } // 方式2 TODO: 优化下面这段代码,没太看懂这一块的背景 var registerParam = { BaseEdge: _View.BaseEdge, BaseEdgeModel: _Model.BaseEdgeModel, BaseNode: _View.BaseNode, BaseNodeModel: _Model.BaseNodeModel, RectNode: _View.RectNode, RectNodeModel: _Model.RectNodeModel, CircleNode: _View.CircleNode, CircleNodeModel: _Model.CircleNodeModel, PolygonNode: _View.PolygonNode, PolygonNodeModel: _Model.PolygonNodeModel, TextNode: _View.TextNode, TextNodeModel: _Model.TextNodeModel, LineEdge: _View.LineEdge, LineEdgeModel: _Model.LineEdgeModel, DiamondNode: _View.DiamondNode, DiamondNodeModel: _Model.DiamondNodeModel, PolylineEdge: _View.PolylineEdge, PolylineEdgeModel: _Model.PolylineEdgeModel, BezierEdge: _View.BezierEdge, BezierEdgeModel: _Model.BezierEdgeModel, EllipseNode: _View.EllipseNode, EllipseNodeModel: _Model.EllipseNodeModel, HtmlNode: _View.HtmlNode, HtmlNodeModel: _Model.HtmlNodeModel, // mobx, h: h, type: element, }; // 为了能让后来注册的可以继承前面注册的 // 例如我注册一个“开始节点” // 然后我再想注册一个“立即开始节点” // 注册传递参数改为动态。 // TODO: 确定 extendKey 的作用 this.viewMap.forEach(function (component) { var key = component.extendKey; if (key) { registerParam[key] = component; } }); this.graphModel.modelMap.forEach(function (component) { var key = component.extendKey; if (key) { registerParam[key] = component; } }); if (fn) { var _a = fn(registerParam), ViewClass = _a.view, ModelClass = _a.model; var vClass = ViewClass; // TODO: 确认 ViewClass 类型 if (isObserverView && !vClass.isObserved) { vClass.isObserved = true; vClass = observer(vClass); } this.setView(element, vClass); this.graphModel.setModel(element, ModelClass); } }; /** * 注册元素(节点 or 边) * @param config 注册元素的配置项 * @private */ LogicFlow.prototype.registerElement = function (config) { var ViewComp = config.view; if (config.isObserverView !== false && !ViewComp.isObserved) { ViewComp.isObserved = true; ViewComp = observer(ViewComp); } this.setView(config.type, ViewComp); this.graphModel.setModel(config.type, config.model); }; /** * 批量注册元素 * @param elements 注册的元素 */ LogicFlow.prototype.batchRegister = function (elements) { var _this = this; if (elements === void 0) { elements = []; } forEach(elements, function (element) { _this.registerElement(element); }); }; LogicFlow.prototype.defaultRegister = function () { // LogicFlow default Nodes and Edges var defaultElements = [ // Node { type: 'rect', view: _View.RectNode, model: _Model.RectNodeModel, }, { type: 'circle', view: _View.CircleNode, model: _Model.CircleNodeModel, }, { type: 'polygon', view: _View.PolygonNode, model: _Model.PolygonNodeModel, }, { type: 'text', view: _View.TextNode, model: _Model.TextNodeModel, }, { type: 'ellipse', view: _View.EllipseNode, model: _Model.EllipseNodeModel, }, { type: 'diamond', view: _View.DiamondNode, model: _Model.DiamondNodeModel, }, { type: 'html', view: _View.HtmlNode, model: _Model.HtmlNodeModel, }, // Edge { type: 'line', view: _View.LineEdge, model: _Model.LineEdgeModel, }, { type: 'polyline', view: _View.PolylineEdge, model: _Model.PolylineEdgeModel, }, { type: 'bezier', view: _View.BezierEdge, model: _Model.BezierEdgeModel, }, ]; this.batchRegister(defaultElements); }; /********************************************************* * Node 相关方法 ********************************************************/ /** * 添加节点 * @param nodeConfig 节点配置 * @param eventType 新增节点事件类型,默认EventType.NODE_ADD * @param e MouseEvent 事件 */ LogicFlow.prototype.addNode = function (nodeConfig, eventType, e) { if (eventType === void 0) { eventType = EventType.NODE_ADD; } return this.graphModel.addNode(nodeConfig, eventType, e); }; /** * 删除节点 * @param {string} nodeId 节点Id */ LogicFlow.prototype.deleteNode = function (nodeId) { var nodeModel = this.graphModel.getNodeModelById(nodeId); if (!nodeModel) return false; var nodeData = nodeModel.getData(); var guards = this.options.guards; var isEnableDelete = (guards === null || guards === void 0 ? void 0 : guards.beforeDelete) ? guards.beforeDelete(nodeData) : true; if (isEnableDelete) { this.graphModel.deleteNode(nodeId); } return isEnableDelete; }; /** * 克隆节点 * @param nodeId 节点Id */ LogicFlow.prototype.cloneNode = function (nodeId) { var nodeModel = this.graphModel.getNodeModelById(nodeId); var nodeData = nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getData(); if (nodeData) { var guards = this.options.guards; var isEnableClone = (guards === null || guards === void 0 ? void 0 : guards.beforeClone) ? guards.beforeClone(nodeData) : true; if (isEnableClone) { return this.graphModel.cloneNode(nodeId); } } }; /** * 修改节点的id,如果不传新的id,会内部自动创建一个。 * @param { string } nodeId 将要被修改的id * @param { string } newId 可选,修改后的id * @returns 修改后的节点id, 如果传入的oldId不存在,返回空字符串 */ LogicFlow.prototype.changeNodeId = function (nodeId, newId) { return this.graphModel.changeNodeId(nodeId, newId); }; /** * 修改指定节点类型 * @param nodeId 节点id * @param type 节点类型 */ LogicFlow.prototype.changeNodeType = function (nodeId, type) { this.graphModel.changeNodeType(nodeId, type); }; /** * 获取节点对象 * @param nodeId 节点Id */ LogicFlow.prototype.getNodeModelById = function (nodeId) { return this.graphModel.getNodeModelById(nodeId); }; /** * 获取节点数据 * @param nodeId 节点 */ LogicFlow.prototype.getNodeDataById = function (nodeId) { var nodeModel = this.getNodeModelById(nodeId); return nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getData(); }; /** * 获取所有以此节点为终点的边 * @param { string } nodeId */ LogicFlow.prototype.getNodeIncomingEdge = function (nodeId) { return this.graphModel.getNodeIncomingEdge(nodeId); }; /** * 获取所有以此节点为起点的边 * @param {string} nodeId */ LogicFlow.prototype.getNodeOutgoingEdge = function (nodeId) { return this.graphModel.getNodeOutgoingEdge(nodeId); }; /** * 获取节点连接到的所有起始节点 * @param {string} nodeId */ LogicFlow.prototype.getNodeIncomingNode = function (nodeId) { return this.graphModel.getNodeIncomingNode(nodeId); }; /** * 获取节点连接到的所有目标节点 * @param {string} nodeId */ LogicFlow.prototype.getNodeOutgoingNode = function (nodeId) { return this.graphModel.getNodeOutgoingNode(nodeId); }; /** * 内部保留方法 * 创建一个fakeNode,用于dnd插件拖动节点进画布的时候使用。 */ LogicFlow.prototype.createFakeNode = function (nodeConfig) { var Model = this.graphModel.modelMap.get(nodeConfig.type); if (!Model) { console.warn("\u4E0D\u5B58\u5728\u4E3A".concat(nodeConfig.type, "\u7C7B\u578B\u7684\u8282\u70B9")); return null; } // * initNodeData区分是否为虚拟节点 var fakeNodeModel = new Model(__assign(__assign({}, nodeConfig), { virtual: true }), this.graphModel); this.graphModel.setFakeNode(fakeNodeModel); return fakeNodeModel; }; /** * 内部保留方法 * 移除fakeNode */ LogicFlow.prototype.removeFakeNode = function () { this.graphModel.removeFakeNode(); }; /** * 内部保留方法 * 用于fakeNode显示对齐线 */ LogicFlow.prototype.setNodeSnapLine = function (data) { var _a; (_a = this.snaplineModel) === null || _a === void 0 ? void 0 : _a.setNodeSnapLine(data); }; /** * 内部保留方法 * 用于fakeNode移除对齐线 */ LogicFlow.prototype.removeNodeSnapLine = function () { var _a; (_a = this.snaplineModel) === null || _a === void 0 ? void 0 : _a.clearSnapline(); }; /********************************************************* * Edge 相关方法 ********************************************************/ /** * 设置默认的边类型。 * 也就是设置在节点直接由用户手动绘制的连线类型。 * @param type LFOptions.EdgeType */ LogicFlow.prototype.setDefaultEdgeType = function (type) { this.graphModel.setDefaultEdgeType(type); }; /** * 给两个节点之间添加一条边 * @example * lf.addEdge({ * type: 'polygon' * sourceNodeId: 'node_id_1', * targetNodeId: 'node_id_2', * }) * @param {EdgeConfig} edgeConfig */ LogicFlow.prototype.addEdge = function (edgeConfig) { return this.graphModel.addEdge(edgeConfig); }; /** * 基于id获取边数据 * @param edgeId 边Id * @returns EdgeData */ LogicFlow.prototype.getEdgeDataById = function (edgeId) { var edgeModel = this.getEdgeModelById(edgeId); return edgeModel === null || edgeModel === void 0 ? void 0 : edgeModel.getData(); }; /** * 基于边Id获取边的model * @param edgeId 边的Id * @return model */ LogicFlow.prototype.getEdgeModelById = function (edgeId) { return this.graphModel.getEdgeModelById(edgeId); }; /** * 获取满足条件边的model * @param edgeFilter 过滤条件 * @example * 获取所有起点为节点 A 的边的 model * lf.getEdgeModels({ * sourceNodeId: 'nodeA_id' * }) * 获取所有终点为节点 B 的边的 model * lf.getEdgeModels({ * targetNodeId: 'nodeB_id' * }) * 获取起点为节点 A,终点为节点 B 的边 * lf.getEdgeModels({ * sourceNodeId: 'nodeA_id', * targetNodeId: 'nodeB_id' * }) * @return model数组 */ LogicFlow.prototype.getEdgeModels = function (_a) { var sourceNodeId = _a.sourceNodeId, targetNodeId = _a.targetNodeId; var results = []; var edges = this.graphModel.edges; if (sourceNodeId && targetNodeId) { forEach(edges, function (edge) { if (edge.sourceNodeId === sourceNodeId && edge.targetNodeId === targetNodeId) { results.push(edge); } }); } else if (sourceNodeId) { forEach(edges, function (edge) { if (edge.sourceNodeId === sourceNodeId) { results.push(edge); } }); } else if (targetNodeId) { forEach(edges, function (edge) { if (edge.targetNodeId === targetNodeId) { results.push(edge); } }); } return results; }; /** * 修改边的id, 如果不传新的id,会内部自动创建一个。 * @param { string } edgeId 将要被修改的id * @param { string } newId 可选,修改后的id * @returns 修改后的节点id, 如果传入的oldId不存在,返回空字符串 */ LogicFlow.prototype.changeEdgeId = function (edgeId, newId) { return this.graphModel.changeEdgeId(edgeId, newId); }; /** * 切换边的类型 * @param edgeId 边Id * @param type 边类型 */ LogicFlow.prototype.changeEdgeType = function (edgeId, type) { this.graphModel.changeEdgeType(edgeId, type); }; /** * 删除边 * @param {string} edgeId 边Id */ LogicFlow.prototype.deleteEdge = function (edgeId) { var edgeModel = this.graphModel.getEdgeModelById(edgeId); if (!edgeModel) return false; var edgeData = edgeModel.getData(); var guards = this.options.guards; var isEnableDelete = (guards === null || guards === void 0 ? void 0 : guards.beforeDelete) ? guards.beforeDelete(edgeData) : true; if (isEnableDelete) { this.graphModel.deleteEdgeById(edgeId); } return isEnableDelete; }; /** * 基于给定节点(作为边起点或终点,可以只传其一),删除对应的边 * @param sourceNodeId 边的起点节点ID * @param targetNodeId 边的终点节点ID */ LogicFlow.prototype.deleteEdgeByNodeId = function (_a) { var sourceNodeId = _a.sourceNodeId, targetNodeId = _a.targetNodeId; // TODO: 将下面方法从 this.graphModel 解构,并测试代码功能是否正常(需要确认 this 指向是否有异常) if (sourceNodeId && targetNodeId) { this.graphModel.deleteEdgeBySourceAndTarget(sourceNodeId, targetNodeId); } else if (sourceNodeId) { this.graphModel.deleteEdgeBySource(sourceNodeId); } else if (targetNodeId) { this.graphModel.deleteEdgeByTarget(targetNodeId); } }; /** * 获取节点连接的所有边的model * @param nodeId 节点ID * @returns model数组 */ LogicFlow.prototype.getNodeEdges = function (nodeId) { return this.graphModel.getNodeEdges(nodeId); }; /********************************************************* * Element 相关方法 ********************************************************/ /** * 添加多个元素, 包括边和节点。 * @param nodes * @param edges * @param distance */ LogicFlow.prototype.addElements = function (_a, distance) { var _this = this; var nodes = _a.nodes, edges = _a.edges; if (distance === void 0) { distance = 40; } // TODO: 1. 解决下面方法中 distance 传参缺未使用的问题;该方法在快捷键中有调用 // TODO: 2. review 一下本函数代码逻辑,确认 nodeIdMap 的作用,看是否有优化的空间 console.log('distance', distance); var nodeIdMap = {}; var elements = { nodes: [], edges: [], }; forEach(nodes, function (node) { var nodeId = node.id; var nodeModel = _this.addNode(node); if (nodeId) nodeIdMap[nodeId] = nodeModel.id; elements.nodes.push(nodeModel); }); forEach(edges, function (edge) { var sourceNodeId = edge.sourceNodeId, targetNodeId = edge.targetNodeId; if (nodeIdMap[sourceNodeId]) sourceNodeId = nodeIdMap[sourceNodeId]; if (nodeIdMap[targetNodeId]) targetNodeId = nodeIdMap[targetNodeId]; var edgeModel = _this.graphModel.addEdge(__assign(__assign({}, edge), { sourceNodeId: sourceNodeId, targetNodeId: targetNodeId })); elements.edges.push(edgeModel); }); return elements; }; /** * 将图形选中 * @param id 选择元素ID * @param multiple 是否允许多选,如果为true,不会将上一个选中的元素重置 * @param toFront 是否将选中的元素置顶,默认为true */ LogicFlow.prototype.selectElementById = function (id, multiple, toFront) { if (multiple === void 0) { multiple = false; } if (toFront === void 0) { toFront = true; } this.graphModel.selectElementById(id, multiple); if (!multiple && toFront) { this.graphModel.toFront(id); } }; /** * 移除选中的元素 * @param id 元素ID */ LogicFlow.prototype.deselectElementById = function (id) { this.graphModel.deselectElementById(id); }; /** * 获取选中的元素数据 * @param isIgnoreCheck 是否包括sourceNode和targetNode没有被选中的边,默认包括。 * 注意:复制的时候不能包括此类边, 因为复制的时候不允许悬空的边。 */ LogicFlow.prototype.getSelectElements = function (isIgnoreCheck) { if (isIgnoreCheck === void 0) { isIgnoreCheck = true; } return this.graphModel.getSelectElements(isIgnoreCheck); }; /** * 将所有选中的元素设置为非选中 */ LogicFlow.prototype.clearSelectElements = function () { this.graphModel.clearSelectElements(); }; /** * 获取节点或边对象 * @param id id */ LogicFlow.prototype.getModelById = function (id) { return this.graphModel.getElement(id); }; /** * 获取节点或边的数据 * @param id id */ LogicFlow.prototype.getDataById = function (id) { var _a; return (_a = this.graphModel.getElement(id)) === null || _a === void 0 ? void 0 : _a.getData(); }; /** * 删除元素,在不确定当前id是节点还是边时使用 * @param id 元素id */ LogicFlow.prototype.deleteElement = function (id) { var _a; var _b, _c; var model = this.getModelById(id); if (!model) return false; var callback = (_a = {}, _a[ElementType.NODE] = this.deleteNode, _a[ElementType.EDGE] = this.deleteEdge, _a); return (_c = (_b = callback[model.BaseType]) === null || _b === void 0 ? void 0 : _b.call(this, id)) !== null && _c !== void 0 ? _c : false; }; /** * 设置元素的zIndex. * 注意:默认堆叠模式下,不建议使用此方法。 * @see todo link 堆叠模式 * @param id 元素id * @param zIndex zIndex的值,可以传数字,也支持传入 'top' 和 'bottom' */ LogicFlow.prototype.setElementZIndex = function (id, zIndex) { return this.graphModel.setElementZIndex(id, zIndex); }; /** * 获取指定区域内的所有元素,此区域必须是DOM层。 * 例如鼠标绘制选区后,获取选区内的所有元素。 * @see todo 分层 * @param leftTopPoint 区域左上角坐标, dom层坐标 * @param rightBottomPoint 区域右下角坐标,dom层坐标 * @param wholeEdge * @param wholeNode * @param ignoreHideElement */ LogicFlow.prototype.getAreaElement = function (leftTopPoint, rightBottomPoint, wholeEdge, wholeNode, ignoreHideElement) { if (wholeEdge === void 0) { wholeEdge = true; } if (wholeNode === void 0) { wholeNode = true; } if (ignoreHideElement === void 0) { ignoreHideElement = false; } return this.graphModel .getAreaElement(leftTopPoint, rightBottomPoint, wholeEdge, wholeNode, ignoreHideElement) .map(function (element) { return element.getData(); }); }; /** * 设置元素的自定义属性 * @see http://logicflow.cn/api/detail#setproperties * @param id 元素的id * @param properties 自定义属性 */ LogicFlow.prototype.setProperties = function (id, properties) { var _a; (_a = this.graphModel.getElement(id)) === null || _a === void 0 ? void 0 : _a.setProperties(formatData(properties)); }; /** * 获取元素的自定义属性 * @param id 元素的id * @returns 自定义属性 */ LogicFlow.prototype.getProperties = function (id) { var _a; return (_a = this.graphModel.getElement(id)) === null || _a === void 0 ? void 0 : _a.getProperties(); }; LogicFlow.prototype.deleteProperty = function (id, key) { var _a; (_a = this.graphModel.getElement(id)) === null || _a === void 0 ? void 0 : _a.deleteProperty(key); }; /** * FBI WARNING !!! 慎用 === 不要用 * 修改对应元素 model 中的属性 * 注意:此方法慎用,除非您对logicflow内部有足够的了解。 * 大多数情况下,请使用setProperties、updateText、changeNodeId等方法。 * 例如直接使用此方法修改节点的id,那么就是会导致连接到此节点的边的sourceNodeId出现找不到的情况。 * @param {string} id 元素id * @param {object} attributes 需要更新的属性 */ LogicFlow.prototype.updateAttributes = function (id, attributes) { this.graphModel.updateAttributes(id, attributes); }; /********************************************************* * Text 相关方法 ********************************************************/ /** * 显示节点、连线文本编辑框 * @param id 元素id */ LogicFlow.prototype.editText = function (id) { this.graphModel.editText(id); }; /** * 更新节点或边的文案 * @param id 节点或者边id * @param value 文案内容 */ LogicFlow.prototype.updateText = function (id, value) { this.graphModel.updateText(id, value); }; /********************************************************* * EditConfig 相关方法 ********************************************************/ /** * 更新流程图编辑相关设置 * @param {object} config 编辑配置 * @see http://logicflow.cn/api/detail#updateeditconfig */ LogicFlow.prototype.updateEditConfig = function (config) { var _a = this.graphModel, editConfigModel = _a.editConfigModel, transformModel = _a.transformModel; var currentSnapGrid = editConfigModel.snapGrid; editConfigModel.updateEditConfig(config); if ((config === null || config === void 0 ? void 0 : config.stopMoveGraph) !== undefined) { transformModel.updateTranslateLimits(config.stopMoveGraph); } // 静默模式切换时,修改快捷键的启用状态 (config === null || config === void 0 ? void 0 : config.isSilentMode) ? this.keyboard.disable() : this.keyboard.enable(true); // 切换网格对齐状态时,修改网格尺寸 if (!isNil(config === null || config === void 0 ? void 0 : config.snapGrid) && config.snapGrid !== currentSnapGrid) { var _b = this.graphModel.grid.size, size = _b === void 0 ? 1 : _b; this.graphModel.updateGridSize(config.snapGrid ? size : 1); } this.emit(EventType.EDIT_CONFIG_CHANGED, { data: editConfigModel.getConfig(), }); }; /** * 获取流程图当前编辑相关设置 * @see http://logicflow.cn/api/detail#geteditconfig */ LogicFlow.prototype.getEditConfig = function () { return this.graphModel.editConfigModel.getConfig(); }; /********************************************************* * Graph 相关方法 ********************************************************/ /** * 设置主题样式 * @param { object } style 自定义主题样式 * todo docs link */ LogicFlow.prototype.setTheme = function (style, themeMode) { this.graphModel.setTheme(style, themeMode); }; /** * 获取当前主题样式 * @see todo docs link */ LogicFlow.prototype.getTheme = function () { return this.graphModel.getTheme(); }; LogicFlow.prototype.focusByElement = function (id) { var coordinate = undefined; var nodeModel = this.getNodeModelById(id); if (nodeModel) { var _a = nodeModel.getData(), x = _a.x, y = _a.y; coordinate = { x: x, y: y, }; } var edgeModel = this.getEdgeModelById(id); if (edgeModel) { var _b = edgeModel.textPosition, x = _b.x, y = _b.y; coordinate = { x: x, y: y, }; } if (coordinate) { this.focusByCoordinate(coordinate); } }; LogicFlow.prototype.focusByCoordinate = function (coordinate) { var _a = this.graphModel, transformModel = _a.transformModel, width = _a.width, height = _a.height; var x = coordinate.x, y = coordinate.y; transformModel.focusOn(x, y, width, height); }; LogicFlow.prototype.focusOn = function (focusOnArgs) { if (typeof focusOnArgs === 'string') { // string focusOnArgs -> id this.focusByElement(focusOnArgs); } else if ('x' in focusOnArgs && 'y' in focusOnArgs) { // Position focusOnArgs -> coordinate this.focusByCoordinate(focusOnArgs); } else { // FocusOnArgsType var id = focusOnArgs.id, coordinate = focusOnArgs.coordinate; if (id) { this.focusByElement(id); } if (coordinate) { this.focusByCoordinate(coordinate); } } }; /** * 重新设置画布的宽高 * 不传会自动计算画布宽高 */ LogicFlow.prototype.resize = function (width, height) { this.graphModel.resize(width, height); this.options.width = this.graphModel.width; this.options.height = this.graphModel.height; }; /** * 将某个元素放置到顶部。 * 如果堆叠模式为默认模式,则将原置顶元素重新恢复原有层级。 * 如果堆叠模式为递增模式,则将需指定元素zIndex设置为当前最大zIndex + 1。 * @see todo link 堆叠模式 * @param id 元素Id */ LogicFlow.prototype.toFront = function (id) { this.graphModel.toFront(id); }; LogicFlow.prototype.getPointByClient = function (x, y) { if (typeof x === 'object') { return this.graphModel.getPointByClient(x); } else if (typeof y === 'number') { return this.graphModel.getPointByClient({ x: x, y: y, }); } }; /** * 获取流程绘图数据 * 注意: getGraphData返回的数据受到adapter影响,所以其数据格式不一定是logicflow内部图数据格式。 * 如果实现通用插件,请使用getGraphRawData */ LogicFlow.prototype.getGraphData = function () { var params = []; for (var _i = 0; _i < arguments.length; _i++) { params[_i] = arguments[_i]; } var data = this.getGraphRawData(); if (this.adapterOut) { return this.adapterOut.apply(this, __spreadArray([data], __read(params), false)); } return data; }; /** * 获取流程绘图原始数据 * 在存在adapter时,可以使用getGraphRawData获取图原始数据 */ LogicFlow.prototype.getGraphRawData = function () { return this.graphModel.modelToGraphData(); }; /** * 清空画布 */ LogicFlow.prototype.clearData = function () { this.graphModel.clearData(); // 强制刷新数据, 让 preact 清除对已删除节点的引用 this.render({}); }; /********************************************************* * LogicFlow Render方法 ********************************************************/ LogicFlow.prototype.renderRawData = function (graphRawData) { this.graphModel.graphDataToModel(formatData(graphRawData)); if (this.options.history !== false) { this.history.watch(this.graphModel); } render(_jsx(Graph, { getView: this.getView, tool: this.tool, options: this.options, dnd: this.dnd, snaplineModel: this.snaplineModel, graphModel: this.graphModel }), this.container); this.emit(EventType.GRAPH_RENDERED, { data: this.graphModel.modelToGraphData(), graphModel: this.graphModel, }); }; /** * 渲染图 * @example * lf.render({ * nodes: [ * { * id: 'node_1', * type: 'rect', * x: 100, * y: 100 * }, * { * id: 'node_2', * type: 'circle', * x: 300, * y: 200 * } * ], * edges: [ * { * sourceNodeId: 'node_1', * targetNodeId: 'node_2', * type: 'polyline' * } * ] * }) * @param graphData 图数据 */ LogicFlow.prototype.render = function (graphData) { var graphRawData = cloneDeep(graphData); if (this.adapterIn) { graphRawData = this.adapterIn(graphRawData); } this.renderRawData(graphRawData); }; /********************************************************* * History/Resize 相关方法 ********************************************************/ /** * 历史记录操作 * 返回上一步 */ LogicFlow.prototype.undo = function () { if (!this.history.undoAble()) return; // formatData兼容vue数据 var graphData = formatData(this.history.undo()); this.clearSelectElements(); this.graphModel.graphDataToModel(graphData); }; /** * 历史记录操作 * 恢复下一步 */ LogicFlow.prototype.redo = function () { if (!this.history.redoAble()) return; // formatData兼容vue数据 var graphData = formatData(this.history.redo()); this.clearSelectElements(); this.graphModel.graphDataToModel(graphData); }; /** * 放大缩小图形 * @param zoomSize 放大缩小的值,支持传入0-n之间的数字。小于1表示缩小,大于1表示放大。也支持传入true和false按照内置的刻度放大缩小 * @param point 缩放的原点 * @returns {string} -放大缩小的比例 */ LogicFlow.prototype.zoom = function (zoomSize, point) { var transformModel = this.graphModel.transformModel; return transformModel.zoom(zoomSize, point); }; /** * 重置图形的放大缩写比例为默认 */ LogicFlow.prototype.resetZoom = function () { var transformModel = this.graphModel.transformModel; transformModel.resetZoom(); }; /** * 设置图形缩小时,能缩放到的最小倍数。参数为0-1自己。默认0.2 * @param size 图形缩小的最小值 */ LogicFlow.prototype.setZoomMiniSize = function (size) { var transformModel = this.graphModel.transformModel; transformModel.setZoomMiniSize(size); }; /** * 设置图形放大时,能放大到的最大倍数,默认16 * @param size 图形放大的最大值 */ LogicFlow.prototype.setZoomMaxSize = function (size) { var transformModel = this.graphModel.transformModel; transformModel.setZoomMaxSize(size); }; /** * 获取缩放的值和平移的值。 */ LogicFlow.prototype.getTransform = function () { var _a = this.graphModel.transformModel, SCALE_X = _a.SCALE_X, SCALE_Y = _a.SCALE_Y, TRANSLATE_X = _a.TRANSLATE_X, TRANSLATE_Y = _a.TRANSLATE_Y; return { SCALE_X: SCALE_X, SCALE_Y: SCALE_Y, TRANSLATE_X: TRANSLATE_X, TRANSLATE_Y: TRANSLATE_Y, }; }; /** * 平移图 * @param x 向x轴移动距离 * @param y 向y轴移动距离 */ LogicFlow.prototype.translate = function (x, y) { var transformModel = this.graphModel.transformModel; transformModel.translate(x, y); }; /** * 还原图形为初始位置 */ LogicFlow.prototype.resetTranslate = function () { var transformModel = this.graphModel.transformModel; var TRANSLATE_X = transformModel.TRANSLATE_X, TRANSLATE_Y = transformModel.TRANSLATE_Y; this.translate(-TRANSLATE_X, -TRANSLATE_Y); }; /** * 图形画布居中显示 */ LogicFlow.prototype.translateCenter = function () { this.graphModel.translateCenter(); }; /** * 图形适应屏幕大小 * @param verticalOffset number 距离盒子上下的距离, 默认为20 * @param horizontalOffset number 距离盒子左右的距离, 默认为20 */ LogicFlow.prototype.fitView = function (verticalOffset, horizontalOffset) { if (horizontalOffset === undefined) { horizontalOffset = verticalOffset; // 兼容以前的只传一个参数的情况 } this.graphModel.fitView(verticalOffset, horizontalOffset); }; /** * 开启边的动画 * @param edgeId string */ LogicFlow.prototype.openEdgeAnimation = function (edgeId) { this.graphModel.openEdgeAnimation(edgeId); }; /** * 关闭边的动画 * @param edgeId string */ LogicFlow.prototype.closeEdgeAnimation = function (edgeId) { this.graphModel.closeEdgeAnimation(edgeId); }; LogicFlow.prototype.on = function (evt, callback) { this.graphModel.eventCenter.on(evt, callback); }; LogicFlow.prototype.off = function (evt, callback) { this.graphModel.eventCenter.off(evt, callback); }; LogicFlow.prototype.once = function (evt, callback) { this.graphModel.eventCenter.once(evt, callback); }; LogicFlow.prototype.emit = function (evt, arg) { this.graphModel.eventCenter.emit(evt, arg); }; /********************************************************* * 插件系统方法 ********************************************************/ /** * 添加扩展, 待讨论,这里是不是静态方法好一些? * 重复添加插件的时候,把上一次添加的插件的销毁。 * @param extension * @param props */ LogicFlow.use = function (extension, props) { var _a; var pluginName = extension.pluginName; if (!pluginName) { throw new Error("\u8BF7\u7ED9\u63D2\u4EF6\u6307\u5B9A pluginName!"); } // TODO: 应该在何时进行插件的销毁??? // const preExtension = this.extensions.get(pluginName)?.extension // preExtension?.destroy?.() // 该代码应该有问题,因为 preExtension 直接用的是 Constructor,没有实例化。无法访问实例方法 destroy this.extensions.set(pluginName, (_a = {}, _a[pluginFlag] = pluginFlag, _a.extension = extension, _a.props = props, _a)); }; /** * 添加主题模式 * @param themeMode 主题模式 * @param style 主题样式 */ LogicFlow.addThemeMode = function (themeMode, style) { addThemeMode(themeMode, style); }; LogicFlow.removeThemeMode = function (themeMode) { removeThemeMode(themeMode); }; LogicFlow.clearThemeMode = function () { clearThemeMode(); }; LogicFlow.prototype.installPlugins = function (disabledPlugins) { var _this = this; if (disabledPlugins === void 0) { disabledPlugins = []; } var extensionsAddByUse = Array.from(LogicFlow.extensions, function (_a) { var _b = __read(_a, 2), extension = _b[1]; return extension; }); // 安装插件,优先使用个性插件 var extensions = __spreadArray(__spreadArray([], __read(this.plugins), false), __read(extensionsAddByUse), false); forEach(extensions, function (ext) { var extension; var props; if (pluginFlag in ext) { extension = ext.extension; props = ext.props; } else { extension = ext; } var pluginName = extension === null || extension === void 0 ? void 0 : extension.pluginName; if (indexOf(disabledPlugins, pluginName) === -1) { _this.installPlugin(extension, props); } }); }; /** * 加载插件-内部方法 */ LogicFlow.prototype.installPlugin = function (extension, props) { var _a, _b; if ('pluginName' in extension && 'install' in extension) { var pluginName_1 = extension.pluginName, install = extension.install, render_1 = extension.render; if (pluginName_1) { install && install.call(extension, this, LogicFlow); render_1 && this.components.push(render_1.bind(extension)); this.extension[pluginName_1] = extension; } return; } var ExtensionCtor = extension; var pluginName = ExtensionCtor.pluginName; var extensionIns = new ExtensionCtor({ lf: this, LogicFlow: LogicFlow, props: props, // TODO: 这里的 options 应该传入插件对应的 options,而不是全局的 options // 所以应该这么写 this.options.pluginsOptions[ExtensionCtor.pluginName] ?? {} options: (_b = (_a = this.options.pluginsOptions) === null || _a === void 0 ? void 0 : _a[pluginName]) !== null && _b !== void 0 ? _b : {}, }); extensionIns.render && this.components.push(extensionIns.render.bind(extensionIns)); this.extension[pluginName] = extensionIns; }; /** 销毁当前实例 */ LogicFlow.prototype.destroy = function () { var _a; this.clearData(); render(null, this.container); this.keyboard.destroy(); this.graphModel.destroy(); this.tool.destroy(); this.history.destroy(); clearThemeMode(); for (var extensionName in this.extension) { var extensionInstance = this.extension[extensionName]; if ('destroy' in extensionInstance) { (_a = extensionInstance.destroy) === null || _a === void 0 ? void 0 : _a.call(extensionInstance); } } }; // 全局配置的插件,所有的LogicFlow示例都会使用 LogicFlow.extensions = new Map(); return LogicFlow; }()); export { LogicFlow }; // toStringTag (function (LogicFlow) { LogicFlow.toStringTag = "LF.".concat(LogicFlow.name); })(LogicFlow || (LogicFlow = {})); export default LogicFlow;