UNPKG

butterfly-dag

Version:

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

185 lines (165 loc) 5.62 kB
'use strict'; const $ = require('jquery'); const _ = require('lodash'); class GridService { constructor(opts) { this.root = opts.root; this.canvas = opts.canvas; this.domWrapper = _.get(opts, 'canvas.wrapper'); this.canvasHeight = 0; this.canvasWidth = 0; this.dom = null; this.isActive = false; this.theme = _.get(opts, 'theme', {}) || { shapeType: 'circle', // 展示的类型,支持line & circle gap: 5, // 网格间隙 adsorbGap: '5px', // 吸附间距 background: '#fff', // 网格背景颜色 lineColor: '#000', // 网格线条颜色 lineWidth: '1px', // 网格粗细 circleRadiu: 2, // 圆点半径 circleColor: '#000' // 断电颜色 }; } _resize() { this.canvasHeight = $(this.root).height(); this.canvasWidth = $(this.root).width(); $(this.dom).attr('width', this.canvasWidth); $(this.dom).attr('height', this.canvasHeight); } create(options = {}) { this.theme = _.merge(this.theme, options.theme || {}); if (!this.dom) { this.dom = $('<canvas class="butterfly-gird-canvas"></canvas>')[0]; this._resize(); $(this.dom).appendTo(this.root); } if (this.theme.shapeType === 'circle') { this.createCircle(); } else if (this.theme.shapeType === 'line') { this.createLine(); } if (!!this.theme.background) { $(this.dom).css('background', this.theme.background); } this.isActive = true; } createCircle() { let _ctx = this.dom.getContext('2d'); // _ctx.fillStyle = "rgba(0, 0, 0, 1)"; // _ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); _ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); _ctx.beginPath(); _ctx.fillStyle = this.theme.circleColor || '#000'; let _p = Math.PI * 2; let _gap = parseInt(this.theme.gap); _gap = _gap < 5 ? 5 : _gap; for (let i = 0; i < this.canvasWidth; i += _gap) { for (let j = 0; j < this.canvasHeight; j += _gap) { _ctx.moveTo(i, j); _ctx.arc(i, j, this.theme.circleRadiu, 0, _p); } } _ctx.fill(); } createLine() { let _ctx = this.dom.getContext('2d'); _ctx.strokeStyle = this.theme.lineColor || '#000'; _ctx.lineWidth = this.theme.lineWidth || 1; let _gap = parseInt(this.theme.gap); _gap = _gap < 5 ? 5 : _gap; for (let j = 0; j < this.canvasHeight; j += _gap) { _ctx.beginPath(); _ctx.moveTo(0, j); _ctx.lineTo(this.canvasWidth, j); _ctx.stroke(); _ctx.closePath(); } for (let i = 0; i < this.canvasWidth; i += _gap) { _ctx.beginPath(); _ctx.moveTo(i, 0); _ctx.lineTo(i, this.canvasHeight); _ctx.stroke(); _ctx.closePath(); } _ctx.stroke(); } justifyAllCoordinate() { let groups = this.canvas.groups; let nodes = this.canvas.nodes; let _justifyItem = (item, type) => { let _sx = item.left; let _sy = item.top; let _ex = item.left + item.getWidth(); let _ey = item.top + item.getHeight(); let _left = _sx % this.theme.gap; let _right = _ex % this.theme.gap; let _top = _sy % this.theme.gap; let _bottom = _ey % this.theme.gap; let _posLeft = this.theme.gap - _left; let _posRight = this.theme.gap - _right; let _posTop = this.theme.gap - _top; let _posBottom = this.theme.gap - _bottom; let _pos = { left: Infinity, right: Infinity, top: Infinity, bottom: Infinity }; if (_left < _right && _left < _pos['left']) { _pos['left'] = _left; } if (_posLeft < _left && _posLeft < _pos['right']) { _pos['right'] = _posLeft; } if (_right < _left && _right < _pos['right']) { _pos['left'] = _right; } if (_posRight < _right && _posRight < _pos['left']) { _pos['right'] = _posRight; } if (_top < _bottom && _top < _pos['top']) { _pos['top'] = _top; } if (_posTop < _top && _posTop < _pos['bottom']) { _pos['bottom'] = _posTop; } if (_bottom < _top && _bottom < _pos['bottom']) { _pos['top'] = _bottom; } if (_posBottom < _bottom && _posBottom < _pos['top']) { _pos['bottom'] = _posBottom; } let result = [item.left, item.top]; _pos['left'] = _pos['left'] <= this.theme.adsorbGap ? _pos['left'] : Infinity; _pos['right'] = _pos['right'] <= this.theme.adsorbGap ? _pos['right'] : Infinity; _pos['top'] = _pos['top'] <= this.theme.adsorbGap ? _pos['top'] : Infinity; _pos['bottom'] = _pos['bottom'] <= this.theme.adsorbGap ? _pos['bottom'] : Infinity; _pos['left'] < _pos['right'] && (result[0] -= _pos['left']); _pos['right'] < _pos['left'] && (result[0] += _pos['right']); _pos['top'] < _pos['bottom'] && (result[1] -= _pos['top']); _pos['bottom'] < _pos['top'] && (result[1] += _pos['bottom']); if (result[0] !== item.left || result[1] !== item.top) { if (type === 'node') { this.canvas._moveNode(item, result[0], result[1]); } else if (type === 'group') { this.canvas._moveGroup(item, result[0], result[1]); } } }; groups.forEach((_group) => { _justifyItem(_group, 'group'); (_group.nodes || []).forEach((_node) => { _justifyItem(_node, 'node'); }); }); nodes.forEach((_node) => { _justifyItem(_node, 'node'); }); } destroy() { this.dom.remove(); this.isActive = false; } } export default GridService;