UNPKG

butterfly-dag

Version:

一个基于数据驱动的节点式编排组件库,让你有方便快捷定制可视化流程图表

1,686 lines (1,602 loc) 481 kB
import _$e from 'lodash'; import d3Force from 'd3-force'; import dagre from 'dagre'; import { Matrix, SingularValueDecomposition } from 'ml-matrix'; import '@antv/matrix-util'; import $$b from 'jquery'; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function () {}; return { s: F, n: function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function (e) { throw e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function () { it = it.call(o); }, n: function () { var step = it.next(); normalCompletion = step.done; return step; }, e: function (e) { didErr = true; err = e; }, f: function () { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } var EventEmit3$4 = require('eventemitter3'); var Canvas = /*#__PURE__*/function (_EventEmit) { _inherits(Canvas, _EventEmit); function Canvas() { _classCallCheck(this, Canvas); // root 根节点 // layout 布局支持 // zoomable 是否可放大缩小 // moveable 是否可移动 // draggable 是否可拖动节点 // linkable 是否可连接线条 // disLinkable 是否可取消连线 // theme 主题配置 // global 公共配置 return _callSuper(this, Canvas); } // 渲染节点 _createClass(Canvas, [{ key: "draw", value: function draw() {} // 获取节点 }, { key: "getNode", value: function getNode() {} // 获取线条 }, { key: "getEdge", value: function getEdge() {} // 获取节点组 }, { key: "getGroup", value: function getGroup() {} // 添加节点 }, { key: "addNode", value: function addNode() {} // 批量添加节点 }, { key: "addNodes", value: function addNodes() {} // 添加线条 }, { key: "addEdge", value: function addEdge() {} // 批量添加线条 }, { key: "addEdges", value: function addEdges() {} // 批量添加节点组 }, { key: "addGroups", value: function addGroups() {} // 删除节点 }, { key: "removeNode", value: function removeNode() {} // 批量删除节点 }, { key: "removeNodes", value: function removeNodes() {} // 删除线条 }, { key: "removeEdge", value: function removeEdge() {} // 批量删除线条 }, { key: "removeEdges", value: function removeEdges() {} // 删除节点组 }, { key: "removeGroup", value: function removeGroup() {} // 获取相邻的线条 }, { key: "getNeighborEdges", value: function getNeighborEdges() {} // 获取相邻的节点 }, { key: "getNeighborNodes", value: function getNeighborNodes() {} // 获取无环血缘图 }, { key: "getNeighborNodesAndEdgesByLevel", value: function getNeighborNodesAndEdgesByLevel() {} }, { key: "getAdjcentTable", value: function getAdjcentTable() {} // 需要改为内部方法 // 获取缩放值 }, { key: "getZoom", value: function getZoom() {} // 动态设置可缩放 }, { key: "setZoomable", value: function setZoomable() {} // 动态设置缩放值 }, { key: "zoom", value: function zoom() {} // 获取偏移值 }, { key: "getOffset", value: function getOffset() {} // 动态设置可移动 }, { key: "setMoveable", value: function setMoveable() {} // 动态设置移动 }, { key: "move", value: function move() {} // 获取中心点 }, { key: "getOrigin", value: function getOrigin() {} // 动态设置中心点 }, { key: "setOrigin", value: function setOrigin() {} // 获取数据结构 }, { key: "getDataMap", value: function getDataMap() {} // 设置网格模式 }, { key: "setGirdMode", value: function setGirdMode() {} // 设置网格线条 }, { key: "setGuideLine", value: function setGuideLine() {} // 设置辅助线 }, { key: "justifyCoordinate", value: function justifyCoordinate() {} // 设置框选模式 }, { key: "setSelectMode", value: function setSelectMode() {} // 设置某些联合值,即框选的元素 }, { key: "getUnion", value: function getUnion() {} // 设置所有联合值,即框选的元素 }, { key: "getAllUnion", value: function getAllUnion() {} // 添加联合值 }, { key: "add2Union", value: function add2Union() {} // 删除某些联合值 }, { key: "removeUnion", value: function removeUnion() {} // 删除所有联合值 }, { key: "removeAllUnion", value: function removeAllUnion() {} // 聚焦单个节点(看看需要合并不) }, { key: "focusNodeWithAnimate", value: function focusNodeWithAnimate() {} // 聚焦某些节点 }, { key: "focusNodesWithAnimate", value: function focusNodesWithAnimate() {} // 画布坐标转换为终端坐标 }, { key: "canvas2terminal", value: function canvas2terminal() {} // 终端坐标转换为画布坐标 }, { key: "terminal2canvas", value: function terminal2canvas() {} // 保存为图片 }, { key: "save2img", value: function save2img() {} // ********* 需要优化的api ********* // 更新画布的大小 }, { key: "updateRootResize", value: function updateRootResize() {} // ********* 需要新增的api ********* // 单击的回调 }, { key: "click", value: function click() {} // 双击的回调 }, { key: "doubleClick", value: function doubleClick() {} // 右键的回调 }, { key: "onContextmenu", value: function onContextmenu() {} // 集成menu // 生成/关闭缩略图 }]); return Canvas; }(EventEmit3$4); var EventEmit3$3 = require('eventemitter3'); var Node = /*#__PURE__*/function (_EventEmit) { _inherits(Node, _EventEmit); function Node() { _classCallCheck(this, Node); // id 节点唯一标志 // top 坐标y // left 坐标x // group 存在于哪个节点组上 // dom 节点的dom元素 // draggable 该节点是否能拖动标志,可覆盖全局的 // options 数据的透传 // _on 节点发送事件 // _emit 节点发送事件 // _global 全局的配置 // 需要优化的 // scope scope相同可拉进group里面 // endpoints endpoint对象 // _endpointsData 真实的endpoint数据 // _isMoving 标识是否在移动做,兼容冒泡 return _callSuper(this, Node); } // 渲染节点 _createClass(Node, [{ key: "draw", value: function draw() {} // 获取锚点 }, { key: "getEndpoint", value: function getEndpoint() {} // 添加锚点 }, { key: "addEndpoint", value: function addEndpoint() {} // 删除锚点 }, { key: "removeEndpoint", value: function removeEndpoint() {} // 移动节点 }, { key: "moveTo", value: function moveTo() {} // 获取宽度 }, { key: "getWidth", value: function getWidth() {} // 获取高度 }, { key: "getHeight", value: function getHeight() {} // 设置该节点是否能拖动,能覆盖全局 }, { key: "setDraggable", value: function setDraggable() {} // remove的方法 }, { key: "remove", value: function remove() {} // 销毁的方法 }, { key: "destroy", value: function destroy() {} // ********* 需要新增的api ********* // focus回调 }, { key: "focus", value: function focus() {} // unFocus回调 }, { key: "unFocus", value: function unFocus() {} // 单击的回调 }, { key: "click", value: function click() {} // 双击的回调 }, { key: "doubleClick", value: function doubleClick() {} // 右键的回调 }, { key: "onContextmenu", value: function onContextmenu() {} // hover的回调 }, { key: "hover", value: function hover() {} }]); return Node; }(EventEmit3$3); var EventEmit3$2 = require('eventemitter3'); var Endpoint = /*#__PURE__*/function (_EventEmit) { _inherits(Endpoint, _EventEmit); function Endpoint() { _classCallCheck(this, Endpoint); return _callSuper(this, Endpoint); } return _createClass(Endpoint); }(EventEmit3$2); var $$a = require('jquery'); var _$d = require('lodash'); var BaseEndpoint = /*#__PURE__*/function (_Endpoint) { _inherits(BaseEndpoint, _Endpoint); function BaseEndpoint(opts) { var _this; _classCallCheck(this, BaseEndpoint); _this = _callSuper(this, BaseEndpoint, [opts]); _this.id = opts.id; _this.options = opts; _this.orientation = opts.orientation || [0, -1]; _this.pos = opts.pos; _this.type = opts.type; _this.nodeType = _$d.get(opts, 'nodeType', 'node'); _this.nodeId = _$d.get(opts, '_node.id'); _this.root = opts.root; _this.scope = opts.scope; _this.expandArea = opts.expandArea; _this.limitNum = opts.limitNum; // 已连接数 _this.connectedNum = 0; _this.options = opts; // 鸭子辨识手动判断类型 _this.__type = 'endpoint'; // 假如锚点在节点上则有值 _this._node = opts._node; _this._global = opts._global; _this._on = opts._on; _this._emit = opts._emit; // 相对坐标 _this._top = 0; _this._left = 0; // 相对于画布的绝对坐标 _this._posTop = 0; _this._posLeft = 0; _this._width = 0; _this._height = 0; // 拉线时候可连接的标志 _this._linkable = false; _this._coordinateService = null; _this.dom = null; // 判断自定义锚点 _this._isInitedDom = false; if (opts.dom) { _this.dom = opts.dom; _this._isInitedDom = true; } // 判断是否初始化过位置 _this._isInitPos = false; //虚拟滚动对象 _this._virtualScrollUtil = opts._virtualScrollUtil; return _this; } _createClass(BaseEndpoint, [{ key: "_init", value: function _init(obj) { this._coordinateService = obj._coordinateService; if (obj.nodeType) { this.nodeType = obj.nodeType; } // 计算锚点起始值 if (!this._isInitedDom) { this.dom = this.draw({ id: this.id, orientation: this.orientation, pos: this.pos, dom: this.dom, root: this.root, type: this.type, options: this.options }); } else { // 计算width,height,left,top this._width = $$a(this.dom).outerWidth(); this._height = $$a(this.dom).outerHeight(); var box = $$a(this.dom)[0].getBoundingClientRect(); this._left = this._coordinateService._terminal2canvas('x', box.left); this._top = this._coordinateService._terminal2canvas('y', box.top); this._posTop = this._top; this._posLeft = this._left; } this.attachEvent(); } }, { key: "draw", value: function draw(obj) { var _dom = obj.dom; if (!_dom) { _dom = $$a('<div class="butterflie-circle-endpoint"></div>').attr('id', this.id); } else { _dom = $$a(_dom); } return _dom[0]; } }, { key: "updatePos", value: function updatePos() { var dom = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.dom; var orientation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.orientation; var pos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.pos; var isNotEmitEvent = arguments.length > 3 ? arguments[3] : undefined; var _isVirtualHidden = this._node.__type === 'node' ? this._virtualScrollUtil.isHiddenNode(this._node.id) : this._virtualScrollUtil.isHiddenGroup(this._node.id); if (_isVirtualHidden) { if (!this._isInitPos) { this._posTop = this._top = this._node.top; this._posLeft = this._left = this._node.left; } return; } if (this._isInitedDom) { // 计算width,height,left,top this._width = $$a(this.dom).outerWidth(); this._height = $$a(this.dom).outerHeight(); // 计算锚点起始值 var box = $$a(this.dom)[0].getBoundingClientRect(); this._left = this._coordinateService._terminal2canvas('x', box.left); this._top = this._coordinateService._terminal2canvas('y', box.top); // this._left = this._coordinateService._terminal2canvas('x', $(this.dom).offset().left); // this._top = this._coordinateService._terminal2canvas('y', $(this.dom).offset().top); this._posLeft = this._left; this._posTop = this._top; } else { var _currentNode = this._node; var _currentDom = $$a(this._node.dom); this.nodeType; // 分情况弄好方向和位置 var nodeW = _currentDom.outerWidth(); var nodeH = _currentDom.outerHeight(); var targetDom = null; var targetDomW = 0; var targetDomH = 0; if (this.root) { targetDom = _currentDom.find(this.root); targetDomW = targetDom.width(); targetDomH = targetDom.height(); } this._width = $$a(dom).outerWidth(); this._height = $$a(dom).outerHeight(); // 计算节点本身的偏移量 var eOffsetX = this._width / 2; var eOffsetY = this._height / 2; var _offsetTop = 0; var _offsetLeft = 0; var _orientation = orientation || this.orientation || [0, -1]; var _pos = pos || this.pos || [_orientation[0] === 0 ? 0.5 : 0, _orientation[1] === 0 ? 0.5 : 0]; var result = [0, 0]; var _ox = _orientation[0]; var _oy = _orientation[1]; var _px = _pos[0]; var _py = _pos[1]; if (_ox === 0) { result[0] = !this.root ? nodeW * _px - eOffsetX : targetDomW * _px - eOffsetX; } else if (_ox === -1) { result[0] = 0 - eOffsetX; } else if (_ox === 1) { result[0] = !this.root ? nodeW - eOffsetX : targetDomW - eOffsetX; } if (_oy === 0) { result[1] = !this.root ? nodeH * _py - eOffsetY : targetDomH * _py - eOffsetY; } else if (_oy === -1) { result[1] = 0 - eOffsetY; } else if (_oy === 1) { result[1] = !this.root ? nodeH - eOffsetY : targetDomH - eOffsetY; } // 计算绝对定位 if (_currentNode && !this.root) { _offsetTop += _currentNode.top; _offsetLeft += _currentNode.left; } else if (_currentNode && this.root) { // 计算传入的dom距离跟节点 var nodeDomOffsets = _currentDom.offset(); var targetDomOffsets = targetDom.offset(); // 先计算目标节点和父节点得差值再加上父节点的offset _offsetTop += targetDomOffsets.top - nodeDomOffsets.top + _currentNode.top; _offsetLeft += targetDomOffsets.left - nodeDomOffsets.left + _currentNode.left; } this._top = result[1] + _offsetTop; this._left = result[0] + _offsetLeft; this._posTop = this._top; this._posLeft = this._left; if (_currentNode._group) { var _groupPos = this._getGroupPos(_currentNode._group); this._posTop += _groupPos.top; this._posLeft += _groupPos.left; } $$a(dom).css('top', this._top).css('left', this._left); this.updated && this.updated(); } this._isInitPos = true; if (!isNotEmitEvent) { this.emit('InnerEvents', { type: 'endpoint:updatePos', point: this }); } } }, { key: "_getGroupPos", value: function _getGroupPos(group) { var targetGroup = group; var top = 0; var left = 0; while (targetGroup) { top += targetGroup.top; left += targetGroup.left; targetGroup = targetGroup._group; } return { top: top, left: left }; } }, { key: "hasConnection", value: function hasConnection() { return this.connectedNum > 0; } }, { key: "moveTo", value: function moveTo(x, y) { this._top = y; this._left = x; this._posTop = this._top; this._posLeft = this._left; if (!this._isInitedDom) { $$a(this.dom).css('top', y).css('left', x); if (_$d.get(this, '_node._group')) { this._posTop += this._node._group.top; this._posLeft += this._node._group.left; } } } }, { key: "linkable", value: function linkable() { $$a(this.dom).addClass('linkable'); } }, { key: "unLinkable", value: function unLinkable() { $$a(this.dom).removeClass('linkable'); } }, { key: "hoverLinkable", value: function hoverLinkable() { $$a(this.dom).addClass('hover'); } }, { key: "unHoverLinkable", value: function unHoverLinkable() { $$a(this.dom).removeClass('hover'); } }, { key: "attachEvent", value: function attachEvent() { var _this2 = this; $$a(this.dom).on('mousedown', function (e) { var LEFT_KEY = 0; if (e.button !== LEFT_KEY) { return; } e.preventDefault(); e.stopPropagation(); _this2.emit('InnerEvents', { type: 'endpoint:drag', data: _this2 }); }); } }, { key: "emit", value: function emit(type, data) { _get(_getPrototypeOf(BaseEndpoint.prototype), "emit", this).call(this, type, data); this._emit(type, data); } }, { key: "on", value: function on(type, callback) { _get(_getPrototypeOf(BaseEndpoint.prototype), "on", this).call(this, type, callback); this._on(type, callback); } }, { key: "destroy", value: function destroy(isNotEvent) { if (!isNotEvent) { $$a(this.dom).off(); $$a(this.dom).remove(); this.removeAllListeners(); } else { $$a(this.dom).detach(); } } }]); return BaseEndpoint; }(Endpoint); var $$9 = require('jquery'); var _$c = require('lodash'); var BaseNode = /*#__PURE__*/function (_Node) { _inherits(BaseNode, _Node); function BaseNode(opts) { var _this; _classCallCheck(this, BaseNode); _this = _callSuper(this, BaseNode, [opts]); _this.id = opts.id; _this.scope = opts.scope; _this.group = opts.group; _this.top = opts.top || 0; _this.left = opts.left || 0; _this.dom = opts.dom || null; _this.draggable = opts.draggable; _this.options = opts; // 鸭子辨识手动判断类型 _this.__type = 'node'; _this._on = opts._on; _this._emit = opts._emit; _this._global = opts._global; // endpoint 这部分需要考虑 _this.endpoints = []; _this._endpointsData = opts.endpoints; _this._endpointLimitNum = opts._endpointLimitNum; // 标识是否在移动做,兼容冒泡 _this._isMoving = false; // 长宽 _this.width = undefined; _this.height = undefined; _this._isForceUpdateSize = false; // 虚拟滚动对象 _this._virtualScrollUtil = opts._virtualScrollUtil; return _this; } _createClass(BaseNode, [{ key: "draw", value: function draw(obj) { var _dom = obj.dom; if (!_dom) { _dom = $$9('<div></div>').attr('class', 'node').attr('id', obj.id); } var node = $$9(_dom); if (obj.top !== undefined) { node.css('top', "".concat(obj.top, "px")); } if (obj.left !== undefined) { node.css('left', "".concat(obj.left, "px")); } this.updated && this.updated(); return node[0]; } }, { key: "focus", value: function focus() {} }, { key: "unFocus", value: function unFocus() {} }, { key: "addEndpoint", value: function addEndpoint(obj, isInited) { if (isInited) { this.emit('InnerEvents', { type: 'node:addEndpoint', data: obj, isInited: isInited }); return obj; } // 这部分可能还需要想一下 var EndpointClass = obj.Class || BaseEndpoint; var endpoint = new EndpointClass(_$c.assign({ limitNum: obj.limitNum || this._endpointLimitNum, _on: this._on, _emit: this._emit, _virtualScrollUtil: this._virtualScrollUtil, _node: this, _global: this._global }, obj)); this.emit('InnerEvents', { type: 'node:addEndpoint', data: endpoint }); var nodeZindex = $$9(this.dom).css('z-index'); if (nodeZindex !== 'auto') { $$9(endpoint.dom).css('z-index', Number(nodeZindex) + 1); } this.endpoints.push(endpoint); return endpoint; } }, { key: "removeEndpoint", value: function removeEndpoint(pointId) { var rmEndpointIndex = _$c.findIndex(this.endpoints, function (point) { return point.id === pointId; }); if (rmEndpointIndex !== -1) { var rmEndpoint = this.endpoints.splice(rmEndpointIndex, 1)[0]; this.emit('InnerEvents', { type: 'node:removeEndpoint', data: rmEndpoint }); rmEndpoint.destroy(); return rmEndpoint; } } }, { key: "getEndpoint", value: function getEndpoint(pointId, type) { return _$c.find(this.endpoints, function (point) { if (!point.type || point.type === 'onlyConnect') { return pointId === point.id; } else { return pointId === point.id && (type && type === point.type || !type); } }); } }, { key: "_init", value: function _init() { var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (this._isInited) { return; } // 这里可以抽象下,和constructor对比 if (obj.left) { this.left = obj.left; } if (obj.top) { this.top = obj.top; } if (obj._isDeleteGroup) { this.group = undefined; this._group = undefined; } else { obj.group && (this.group = obj.group); } delete obj._isDeleteGroup; this._isInited = true; if (obj.dom) { this.dom = obj.dom; obj.left && $$9(this.dom).css('left', "".concat(obj.left, "px")); obj.top && $$9(this.dom).css('top', "".concat(obj.top, "px")); } else { this.dom = this.draw(_$c.assign({ id: this.id, top: this.top, left: this.left, dom: this.dom, options: this.options }, obj)); } if (!this._hasEventListener) { this._addEventListener(); this._hasEventListener = true; } } // drag的时候移动的api }, { key: "_moveTo", value: function _moveTo(x, y) { var _this2 = this; // 自身移动 $$9(this.dom).css('top', y).css('left', x); // 所在的点移动 this.endpoints.forEach(function (item) { item.moveTo(x - _this2.left + item._left, y - _this2.top + item._top); }); this.top = y; this.left = x; } }, { key: "moveTo", value: function moveTo(x, y, isNotEventEmit) { if (x === this.left && y === this.top) { return; } this.emit('InnerEvents', { type: 'node:move', node: this, x: x, y: y, isNotEventEmit: isNotEventEmit }); } }, { key: "getWidth", value: function getWidth(useCache) { if (this.virtualHidden) { return this.width; } if (!useCache || !this.width || this._isForceUpdateSize) { this.width = $$9(this.dom).outerWidth(); this._isForceUpdateSize = false; } return this.width; } }, { key: "getHeight", value: function getHeight(useCache) { if (this.virtualHidden) { return this.height; } if (!useCache || !this.height || this._isForceUpdateSize) { this.height = $$9(this.dom).outerHeight(); this._isForceUpdateSize = false; } return this.height; } }, { key: "_createEndpoint", value: function _createEndpoint(isInited) { var _this3 = this; if (isInited) { this.endpoints.forEach(function (item) { return _this3.addEndpoint(item, isInited); }); } else if (this._endpointsData) { this._endpointsData.map(function (item) { return _this3.addEndpoint(item); }); } } }, { key: "_addEventListener", value: function _addEventListener() { var _this4 = this; var _beforeStatus = { timer: 0, x: 0, y: 0 }; // todo 做事件代理的形式 $$9(this.dom).on('mousedown', function (e) { var LEFT_KEY = 0; if (e.button !== LEFT_KEY) { return; } if (_$c.isFunction(_this4.canMouseDown) && !_this4.canMouseDown(e)) { return; } if (!['SELECT', 'INPUT', 'RADIO', 'CHECKBOX', 'TEXTAREA'].includes(e.target.nodeName)) { e.preventDefault(); } _beforeStatus = { timer: new Date().getTime(), x: _this4.left, y: _this4.top }; if (_this4.draggable) { _this4._isMoving = true; _this4.emit('InnerEvents', { type: 'node:dragBegin', data: _this4 }); } else { // 单纯为了抛错事件给canvas,为了让canvas的dragtype不为空,不会触发canvas:click事件 _this4.emit('InnerEvents', { type: 'node:mouseDown', data: _this4 }); } }); $$9(this.dom).on('mouseup', function (e) { if (_$c.isFunction(_this4.canMouseUp) && !_this4.canMouseUp(e)) { return; } var _currentStatus = { timer: new Date().getTime(), x: _this4.left, y: _this4.top }; if (_currentStatus.timer - _beforeStatus.timer < 300 || Math.abs(_beforeStatus.x - _currentStatus.x) < 20 && Math.abs(_beforeStatus.y - _currentStatus.y) < 20) { _this4.emit('system.node.click', { node: _this4 }); _this4.emit('events', { type: 'node:click', node: _this4 }); } }); // todo: 尝试使用上面mouseup的机制来代替click的机制 // $(this.dom).on('click', (e) => { // if(_.isFunction(this.canClick) && !this.canClick(e)) { // return; // } // e.preventDefault(); // e.stopPropagation(); // this.emit('system.node.click', { // node: this // }); // this.emit('events', { // type: 'node:click', // node: this // }); // }); this.setDraggable(this.draggable); } }, { key: "setDraggable", value: function setDraggable(draggable) { this.draggable = draggable; } }, { key: "remove", value: function remove() { this.emit('InnerEvents', { type: 'node:delete', data: this }); } }, { key: "emit", value: function emit(type, data) { _get(_getPrototypeOf(BaseNode.prototype), "emit", this).call(this, type, data); this._emit(type, data); } }, { key: "on", value: function on(type, callback) { _get(_getPrototypeOf(BaseNode.prototype), "on", this).call(this, type, callback); this._on(type, callback); } }, { key: "destroy", value: function destroy(isNotEvent) { if (!isNotEvent) { this.endpoints.forEach(function (item) { !item._isInitedDom && item.destroy(); }); $$9(this.dom).remove(); this.removeAllListeners(); this._hasEventListener = false; } else { this.endpoints.forEach(function (item) { !item._isInitedDom && item.destroy(isNotEvent); }); $$9(this.dom).detach(); } this._isInited = false; } }]); return BaseNode; }(Node); // 获取画布所有属性 var canvas = null; function prepareAvoidObstaclesInfo(_canvas) { canvas = _canvas; } function getAvoidObstaclesInfo() { return { nodes: _$e.get(canvas, 'nodes', []).map(function (item) { return { id: item.id, left: item.left, top: item.top, width: item.width || item.options.width || 100, height: item.height || item.options.height || 45 }; }), edges: _$e.get(canvas, 'nodes', []).map(function (item) { return item.options; }) }; } function _calcOrientation(beginX, beginY, endX, endY, orientationLimit) { var _calcWithLimit = function _calcWithLimit(rank) { if (orientationLimit) { var _loop = function _loop(i) { var isInLimit = _$e.some(orientationLimit, function (limit) { return limit === rank[i]; }); if (isInLimit) { return { v: rank[i] }; } }, _ret; for (var i = 0; i < rank.length; i++) { _ret = _loop(i); if (_ret) return _ret.v; } return rank[0]; } else { return rank[0]; } }; // 计算orientation var posX = endX - beginX; var posY = endY - beginY; var orientation = null; // 斜率 var k = Math.abs(posY / posX); if (posX === 0 || posY === 0) { if (posX === 0) { orientation = posY >= 0 ? _calcWithLimit(['Top', 'Left', 'Right', 'Bottom']) : orientation; orientation = posY < 0 ? _calcWithLimit(['Bottom', 'Left', 'Right', 'Top']) : orientation; } if (posY === 0) { orientation = posX >= 0 ? _calcWithLimit(['Right', 'Top', 'Bottom', 'Left']) : orientation; orientation = posX < 0 ? _calcWithLimit(['Left', 'Top', 'Bottom', 'Right']) : orientation; } } else if (posX > 0 && posY > 0) { if (k > 1) { orientation = _calcWithLimit(['Top', 'Left', 'Right', 'Bottom']); // orientation = [0, -1]; } else { orientation = _calcWithLimit(['Left', 'Top', 'Bottom', 'Right']); // orientation = [-1, 0]; } } else if (posX < 0 && posY > 0) { if (k > 1) { orientation = _calcWithLimit(['Top', 'Right', 'Left', 'Bottom']); // orientation = [0, -1]; } else { orientation = _calcWithLimit(['Right', 'Top', 'Bottom', 'Left']); // orientation = [1, 0]; } } else if (posX < 0 && posY < 0) { if (k > 1) { orientation = _calcWithLimit(['Bottom', 'Right', 'Left', 'Top']); // orientation = [0, 1]; } else { orientation = _calcWithLimit(['Right', 'Bottom', 'Top', 'Left']); // orientation = [1, 0]; } } else { if (k > 1) { orientation = _calcWithLimit(['Bottom', 'Left', 'Right', 'Top']); // orientation = [0, 1]; } else { orientation = _calcWithLimit(['Left', 'Bottom', 'Top', 'Right']); // orientation = [-1, 0]; } } switch (orientation) { case 'Left': return [-1, 0]; case 'Right': return [1, 0]; case 'Top': return [0, -1]; case 'Bottom': return [0, 1]; } } function _findControlPoint(point, sourcePoint, targetPoint, _so, _to) { // 曲率,可配置的 var majorAnchor = 10; // 偏移,定死的 var minorAnchor = 10; var result = []; // 特殊处理完全水平和垂直的情况 if (sourcePoint.pos[0] === targetPoint.pos[0] && _so[1] !== _to[1] && _so[0] === 0 && _to[0] === 0) { result = [point[0], point[1] + majorAnchor * _so[1]]; return result; } if (sourcePoint.pos[1] === targetPoint.pos[1] && _so[0] !== _to[0] && _so[1] === 0 && _to[1] === 0) { result = [point[0] + majorAnchor * _so[0], point[1]]; return result; } // 平常情况 var perpendicular = _so[0] !== _to[0] || _so[1] === _to[1]; if (!perpendicular) { if (_so[0] === 0) { result.push(sourcePoint.pos[0] < targetPoint.pos[0] ? point[0] + minorAnchor : point[0] - minorAnchor); } else { result.push(point[0] - majorAnchor * _so[0]); } if (_so[1] === 0) { result.push(sourcePoint.pos[1] < targetPoint.pos[1] ? point[1] + minorAnchor : point[1] - minorAnchor); } else { result.push(point[1] - majorAnchor * _to[1]); } } else { if (_to[0] === 0) { result.push(targetPoint.pos[0] < sourcePoint.pos[0] ? point[0] + minorAnchor : point[0] - minorAnchor); } else { result.push(point[0] + majorAnchor * _to[0]); } if (_to[1] === 0) { result.push(targetPoint.pos[1] < sourcePoint.pos[1] ? point[1] + minorAnchor : point[1] - minorAnchor); } else { result.push(point[1] + majorAnchor * _so[1]); } } return result; } //二阶贝塞尔曲线 function _findSecondControlPoint(sourcePoint, targetPoint, _so, _to, shapeType) { //中点 var midX = (sourcePoint.pos[0] + targetPoint.pos[0]) / 2; var midY = (sourcePoint.pos[1] + targetPoint.pos[1]) / 2; //四分之一点的位置 var quarterX = midX - (midX - sourcePoint.pos[0]) / 2; var quarterY = midY - (midY - sourcePoint.pos[1]) / 2; //四分之三位置 var threeQuarterX = midX + (midX - sourcePoint.pos[0]) / 2; var threeQuarterY = midY + (midY - sourcePoint.pos[1]) / 2; var basicPointX = midX; var basicPointY = midY; if (shapeType === "Bezier2-1") { basicPointX = midX; basicPointY = midY; } else if (shapeType === "Bezier2-2") { basicPointX = quarterX; basicPointY = quarterY; } else if (shapeType === "Bezier2-3") { basicPointX = threeQuarterX; basicPointY = threeQuarterY; } var ctrlPoint; var offset; var _width = Math.abs(sourcePoint.pos[0] - sourcePoint.pos[0]); var _height = Math.abs(sourcePoint.pos[1] - targetPoint.pos[1]); var dist = Math.sqrt(_width * _width + _height * _height); //正常情况 var midK = (targetPoint.pos[1] - sourcePoint.pos[1]) / (targetPoint.pos[0] - sourcePoint.pos[0]); if (midK === 0) { if (sourcePoint.pos[0] < targetPoint.pos[0] && _so[0] === 1 && _to[0] === -1 || sourcePoint.pos[0] > targetPoint.pos[0] && _so[0] === -1 && _to[0] === 1 || sourcePoint.pos[1] < targetPoint.pos[1] && _so[1] === 1 && _to[1] === -1 || sourcePoint.pos[1] > targetPoint.pos[1] && _so[1] === -1 && _to[1] === 1) { return ctrlPoint = [midX, midY]; } } var k = -1 / midK; var b = basicPointY - k * basicPointX; offset = Math.sqrt(3) * dist / 6; var t; var _sum0 = _so[0] + _to[0]; var _sum1 = _so[1] + _to[1]; if (targetPoint.pos[0] < sourcePoint.pos[0] && targetPoint.pos[1] < sourcePoint.pos[1] && (_sum0 === 0 && _sum1 === 0 || _sum0 === 1 && _sum1 === -1)) { t = 1; } else if (targetPoint.pos[0] > sourcePoint.pos[0] && targetPoint.pos[1] < sourcePoint.pos[1] && _sum0 === 1 && _sum1 === 1) { t = 1; } else if (targetPoint.pos[0] < sourcePoint.pos[0] && targetPoint.pos[1] > sourcePoint.pos[1] && (_sum0 === 0 && _sum1 === 0 || _sum0 === 1 && _sum1 === 1)) { t = 1; } else if (targetPoint.pos[0] > sourcePoint.pos[0] && targetPoint.pos[1] > sourcePoint.pos[1] && _sum0 === 1 && _sum1 === -1) { t = 1; } else { t = -1; } ctrlPoint = [basicPointX + offset * t, k * (basicPointX + offset * t) + b]; //特殊情况: var percent = 0.25; var minorDist = 100; offset = dist * percent + minorDist; var so_offsetX = 0; var so_offsetY = 0; var to_offsetX = 0; var to_offsetY = 0; if (_so[0] === -1 && targetPoint.pos[0] > sourcePoint.pos[0] || _so[0] === 1 && targetPoint.pos[0] < sourcePoint.pos[0] || _so[1] === 1 && targetPoint.pos[1] < sourcePoint.pos[1] || _so[1] === -1 && targetPoint.pos[1] > sourcePoint.pos[1]) { if (_so[0] !== 0) { so_offsetX = offset * _so[0]; } if (_so[1] !== 0) { so_offsetY = offset * _so[1]; } return ctrlPoint = [sourcePoint.pos[0] + so_offsetX, sourcePoint.pos[1] + so_offsetY]; } if (_so[0] === _to[0] && _so[1] === _to[1] || _so[0] !== 0 && targetPoint.pos[1] < sourcePoint.pos[1] && _to[1] === -1 || _so[0] !== 0 && targetPoint.pos[1] > sourcePoint.pos[1] && _to[1] === 1 || _so[1] !== 0 && targetPoint.pos[0] < sourcePoint.pos[0] && _to[0] === -1 || _so[1] !== 0 && targetPoint.pos[0] > sourcePoint.pos[0] && _to[0] === 1) { if (_to[0] !== 0) { to_offsetX = offset * _to[0]; } else if (_to[1] !== 0) { to_offsetY = offset * _to[1]; } ctrlPoint = [targetPoint.pos[0] + to_offsetX, targetPoint.pos[1] + to_offsetY]; } return ctrlPoint; } function _findManhattanPoint(points, pos) { var result = undefined; var gap = Infinity; for (var i = 0; i < points.length - 1; i++) { var _dir = points[i].x === points[i + 1].x ? 'vertical' : 'horizontal'; var _from = points[i]; var _to = points[i + 1]; if (_dir === 'vertical') { if (gap > Math.abs(pos.x - _from.x)) { gap = Math.abs(pos.x - _from.x); result = { from: _from, to: _to, direction: _dir, index: i }; } } else { if (gap > Math.abs(pos.y - _from.y)) { gap = Math.abs(pos.y - _from.y); result = { from: _from, to: _to, direction: _dir, index: i }; } } } return result; } var drawAdvancedBezier = function drawAdvancedBezier(sourcePoint, targetPoint) { if (!sourcePoint.orientation) { sourcePoint.orientation = _calcOrientation(targetPoint.pos[0], targetPoint.pos[1], sourcePoint.pos[0], sourcePoint.pos[1]); } if (!targetPoint.orientation) { targetPoint.orientation = _calcOrientation(sourcePoint.pos[0], sourcePoint.pos[1], targetPoint.pos[0], targetPoint.pos[1]); } // 控制点 var _width = Math.abs(sourcePoint.pos[0] - targetPoint.pos[0]); var _height = Math.abs(sourcePoint.pos[1] - targetPoint.pos[1]); var _so = sourcePoint.orientation; var _to = targetPoint.orientation; var dist = Math.sqrt(_width * _width + _height * _height); // 控制点百分比,可转配置 var percent = 0.25; // 偏差量,可转配置 var minorDist = 30; var so_offsetX = 0; var so_offsetY = 0; if (_so[0] !== 0) { so_offsetX = (dist * percent + minorDist) * _so[0]; } else if (_so[1] !== 0) { so_offsetY = (dist * percent + minorDist) * _so[1]; } var to_offsetX = 0; var to_offsetY = 0; if (_to[0] !== 0) { to_offsetX = (dist * percent + minorDist) * _to[0]; } else if (_to[1] !== 0) { to_offsetY = (dist * percent + minorDist) * _to[1]; } var sourceCtrlPoint = [sourcePoint.pos[0] + so_offsetX, sourcePoint.pos[1] + so_offsetY]; var targetCtrlPoint = [targetPoint.pos[0] + to_offsetX, targetPoint.pos[1] + to_offsetY]; // 起始点 var result = ['M', sourcePoint.pos[0], sourcePoint.pos[1]]; // let result = ['M', targetPoint.pos[0], targetPoint.pos[1]]; // 两个控制点 result = result.concat(['C', sourceCtrlPoint[0], sourceCtrlPoint[1]], targetCtrlPoint[0], targetCtrlPoint[1]); // result = result.concat(['C', targetCtrlPoint[0], targetCtrlPoint[1], sourceCtrlPoint[0], sourceCtrlPoint[1]]); // 结束点 result = result.concat([targetPoint.pos[0], targetPoint.pos[1]]); // result = result.concat([sourcePoint.pos[0], sourcePoint.pos[1]]); return result.join(' '); }; function drawBezier(sourcePoint, targetPoint) { if (!sourcePoint.orientation) { sourcePoint.orientation = _calcOrientation(targetPoint.pos[0], targetPoint.pos[1], sourcePoint.pos[0], sourcePoint.pos[1]); } if (!targetPoint.orientation) { targetPoint.orientation = _calcOrientation(sourcePoint.pos[0], sourcePoint.pos[1], targetPoint.pos[0], targetPoint.pos[1]); } // 控制点 var _width = Math.abs(sourcePoint.pos[0] - targetPoint.pos[0]); var _height = Math.abs(sourcePoint.pos[1] - targetPoint.pos[1]); var _sx = sourcePoint.pos[0] < targetPoint.pos[0] ? _width : 0; var _sy = sourcePoint.pos[1] < targetPoint.pos[1] ? _height : 0; var _tx = sourcePoint.pos[0] < targetPoint.pos[0] ? 0 : _width; var _ty = sourcePoint.pos[1] < targetPoint.pos[1] ? 0 : _height; var _so = sourcePoint.orientation; var _to = targetPoint.orientation; var sourceCtrlPoint = _findControlPoint([_sx, _sy], sourcePoint, targetPoint, _so, _to); var targetCtrlPoint = _findControlPoint([_tx, _ty], targetPoint, sourcePoint, _to, _so); var offsetX = sourcePoint.pos[0] < targetPoint.pos[0] ? sourcePoint.pos[0] : targetPoint.pos[0]; var offsetY = sourcePoint.pos[1] < targetPoint.pos[1] ? sourcePoint.pos[1] : targetPoint.pos[1]; sourceCtrlPoint = [sourceCtrlPoint[0] + offsetX, sourceCtrlPoint[1] + offsetY]; targetCtrlPoint = [targetCtrlPoint[0] + offsetX, targetCtrlPoint[1] + offsetY]; // 起始点 var result = ['M', sourcePoint.pos[0], sourcePoint.pos[1]]; // 两个控制点 result = result.concat(['C', targetCtrlPoint[0], targetCtrlPoint[1], sourceCtrlPoint[0], sourceCtrlPoint[1]]); // 结束点 result = result.concat([targetPoint.pos[0], targetPoint.pos[1]]); return result.join(' '); } function drawStraight(sourcePoint, targetPoint) { var result = ['M', sourcePoint.pos[0], sourcePoint.pos[1], 'L', targetPoint.pos[0], targetPoint.pos[1]]; return result.join(' '); } function _drawFlowSegment(segments, offset) { var current = null; var next = null; var lw = 1; // strokeWidth,线条的粗细 var result = []; var _drawStraight = function _drawStraight(d) { return ['M', d.x1 + offset.x, d.y1 + offset.y, 'L', d.x2 + offset.x, d.y2 + offset.y]; }; // let offsetX = sourcePoint.pos[0] < targetPoint.pos[0] ? sourcePoint.pos[0] : targetPoint.pos[0]; // let offsetY = sourcePoint.pos[1] < targetPoint.pos[1] ? sourcePoint.pos[1] : targetPoint.pos[1]; for (var i = 0; i < segments.length - 1; i++) { current = current || _$e.cloneDeep(segments[i]); next = _$e.cloneDeep(segments[i + 1]); { // dx + dy are used to adjust for line width. var dx = current[2] === current[0] ? 0 : current[2] > current[0] ? lw / 2 : -(lw / 2); var dy = current[3] === current[1] ? 0 : current[3] > current[1] ? lw / 2 : -(lw / 2); var _line = _drawStraight({ x1: current[0] - dx, y1: current[1] - dy, x2: current[2] + dx, y2: current[3] + dy }); result = result.concat(_line); } current = next; } if (next !== null) { var _line3 = _drawStraight({ x1: next[0], y1: next[1], x2: next[2], y2: next[3] }); result = result.concat(_line3); } return result.join(' '); } function drawFlow(sourcePoint, targetPoint, orientationLimit) { if (!sourcePoint.orientation) { sourcePoint.orientation = _calcOrientation(targetPoint.pos[0], targetPoint.pos[1], sourcePoint.pos[0], sourcePoint.pos[1], orientationLimit); } if (!targetPoint.orientation) { targetPoint.orientation = _calcOrientation(sourcePoint.pos[0], sourcePoint.pos[1], targetPoint.pos[0], targetPoint.pos[1], orientationLimit); } var stub = 30; // 每部分折线的最小长度 var midpoint = 0.5; // 折线中点 var w = Math.abs(sourcePoint.pos[0] - targetPoint.pos[0]); var h = Math.abs(sourcePoint.pos[1] - targetPoint.pos[1]); var sx = targetPoint.pos[0] < sourcePoint.pos[0] ? w : 0; var sy = targetPoint.pos[1] < sourcePoint.pos[1] ? h : 0; var tx = targetPoint.pos[0] < sourcePoint.pos[0] ? 0 : w; var ty = targetPoint.pos[1] < sourcePoint.pos[1] ?