UNPKG

butterfly-dag

Version:

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

273 lines (238 loc) 7.45 kB
const $ = require('jquery'); const _ = require('lodash'); import './baseEndpoint.less'; import Endpoint from '../interface/endpoint'; class BaseEndpoint extends Endpoint { constructor(opts) { super(opts); this.id = opts.id; this.options = opts; this.orientation = opts.orientation; this.pos = opts.pos; this.type = opts.type; this.nodeType = _.get(opts, 'nodeType', 'node'); this.nodeId = _.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; } } _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 = $(this.dom).outerWidth(); this._height = $(this.dom).outerHeight(); this._left = this._coordinateService._terminal2canvas('x', $(this.dom).offset().left + this._coordinateService.scrollLeft); this._top = this._coordinateService._terminal2canvas('y', $(this.dom).offset().top + this._coordinateService.scrollTop); this._posTop = this._top; this._posLeft = this._left; } this.attachEvent(); } draw(obj) { let _dom = obj.dom; if (!_dom) { _dom = $('<div class="butterflie-circle-endpoint"></div>').attr('id', this.id); } else { _dom = $(_dom); } return _dom[0]; } updatePos(dom = this.dom, orientation = this.orientation, pos = this.pos) { if (this._isInitedDom) { // 计算width,height,left,top this._width = $(this.dom).outerWidth(); this._height = $(this.dom).outerHeight(); // 计算锚点起始值 this._left = this._coordinateService._terminal2canvas('x', $(this.dom).offset().left + this._coordinateService.scrollLeft); this._top = this._coordinateService._terminal2canvas('y', $(this.dom).offset().top + this._coordinateService.scrollTop); this._posLeft = this._left; this._posTop = this._top; } else { let _currentNode = this._node; let _currentDom = $(this._node.dom); let _currentNodeType = this.nodeType; // 分情况弄好方向和位置 const nodeW = _currentDom.outerWidth(); const nodeH = _currentDom.outerHeight(); let targetDom = null; let targetDomW = 0; let targetDomH = 0; if (this.root) { targetDom = _currentDom.find(this.root); targetDomW = targetDom.width(); targetDomH = targetDom.height(); } this._width = $(dom).outerWidth(); this._height = $(dom).outerHeight(); // 计算节点本身的偏移量 const eOffsetX = this._width / 2; const eOffsetY = this._height / 2; let _offsetTop = 0; let _offsetLeft = 0; const _orientation = orientation || this.orientation || [0, -1]; const _pos = pos || this.pos || [_orientation[0] === 0 ? 0.5 : 0, _orientation[1] === 0 ? 0.5 : 0]; const result = [0, 0]; const _ox = _orientation[0]; const _oy = _orientation[1]; const _px = _pos[0]; const _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距离跟节点 const nodeDomOffsets = _currentDom.offset(); const 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) { let _groupPos = this._getGroupPos(_currentNode._group); this._posTop += _groupPos.top; this._posLeft += _groupPos.left; } $(dom) .css('top', this._top) .css('left', this._left); this.updated && this.updated(); } this.emit('InnerEvents', { type: 'endpoint:updatePos', point: this }); } _getGroupPos(group) { let targetGroup = group; let top = 0; let left = 0; while (targetGroup) { top += targetGroup.top; left += targetGroup.left; targetGroup = targetGroup._group; } return { top, left } } hasConnection() { return this.connectedNum > 0; } moveTo(x, y) { this._top = y; this._left = x; this._posTop = this._top; this._posLeft = this._left; if (!this._isInitedDom) { $(this.dom).css('top', y).css('left', x); if (_.get(this, '_node._group')) { this._posTop += this._node._group.top; this._posLeft += this._node._group.left; } } } linkable() { $(this.dom).addClass('linkable'); } unLinkable() { $(this.dom).removeClass('linkable'); } hoverLinkable() { $(this.dom).addClass('hover'); } unHoverLinkable() { $(this.dom).removeClass('hover'); } attachEvent() { $(this.dom).on('mousedown', (e) => { const LEFT_KEY = 0; if (e.button !== LEFT_KEY) { return; } e.preventDefault(); e.stopPropagation(); this.emit('InnerEvents', { type: 'endpoint:drag', data: this }); }); } emit(type, data) { super.emit(type, data); this._emit(type, data); } destroy(isNotEvent) { if (!isNotEvent) { $(this.dom).off(); $(this.dom).remove(); this.removeAllListeners(); } else { $(this.dom).detach(); } } } export default BaseEndpoint;