butterfly-dag
Version:
一个基于数据驱动的节点式编排组件库,让你有方便快捷定制可视化流程图表
100 lines (98 loc) • 3.03 kB
JavaScript
const dagre = require('dagre');
//drage布局
function dagreLayout(param) {
const {nodeSize, rankdir, nodesepFunc, ranksepFunc, nodesep, ranksep, controlPoints} = param;
const {edges = []} = param.data;
const curnode = param.data.nodes;
const nodes = curnode.map((item) => {
return {
id: item.id,
top: item.top,
left: item.left
}
});
// 形成新数组后布局失效
if (!nodes) return;
const g = new dagre.graphlib.Graph();
let nodeSizeFunc;
if (!nodeSize) {
nodeSizeFunc = (d) => {
if (d.size) {
if (_.isArray(d.size)) {
return d.size;
}
return [d.size, d.size];
}
return [40, 40];
};
} else if (_.isArray(nodeSize)) {
nodeSizeFunc = () => nodeSize;
} else {
nodeSizeFunc = () => [nodeSize, nodeSize];
}
let horisep = getFunc(nodesepFunc, nodesep, 50);
let vertisep = getFunc(ranksepFunc, ranksep, 50);
if (rankdir === 'LR' || rankdir === 'RL') {
horisep = getFunc(ranksepFunc, ranksep, 50);
vertisep = getFunc(nodesepFunc, nodesep, 50);
}
nodes.forEach(node => {
const size = nodeSizeFunc(node);
const verti = vertisep(node);
const hori = horisep(node);
const width = size[0] + 2 * hori;
const height = size[1] + 2 * verti;
g.setNode(node.id, {width, height});
});
edges.forEach(edge => {
// dagrejs Wiki https://github.com/dagrejs/dagre/wiki#configuring-the-layout
g.setEdge(edge.source, edge.target, {
weight: edge.weight || 1
});
});
g.setDefaultEdgeLabel(() => ({}));
param.nodes = nodes;
g.setGraph(param);
dagre.layout(g);
let coord;
// 重新布局时g.nodes()可能为undefined
g.nodes().forEach((node) => {
coord = g.node(node);
if (coord) {
const i = nodes.findIndex(it => it.id === node);
nodes[i].left = coord.x;
nodes[i].top = coord.y;
nodes[i].posInfo = {
_out: g._out[node],
_in: g._in[node],
_preds: g._preds[node],
_sucs: g._sucs[node]
}
}
});
g.edges().forEach((edge) => {
coord = g.edge(edge);
const i = edges.findIndex(it => it.source === edge.v && it.target === edge.w);
if (controlPoints && edges[i].type !== 'loop' && edges[i].shape !== 'loop') {
edges[i].controlPoints = coord.points.slice(1, coord.points.length - 1);
}
});
// 将数据挂载到原有数据上,以触发布局
nodes.forEach((item, index) => {
curnode[index].left = item.left;
curnode[index].top = item.top;
curnode[index].posInfo = item.posInfo;
});
}
function getFunc(func, value, defaultValue) {
let resultFunc;
if (func) {
resultFunc = func;
} else if (_.isNumber(value)) {
resultFunc = () => value;
} else {
resultFunc = () => defaultValue;
}
return resultFunc;
}
module.exports = dagreLayout