butterfly-dag
Version:
一个基于数据驱动的节点式编排组件库,让你有方便快捷定制可视化流程图表
185 lines (165 loc) • 5.62 kB
JavaScript
'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;