StructV2/demo/Layouter/AdjoinTableGraph.js
2022-06-29 22:00:12 +08:00

231 lines
6.7 KiB
JavaScript

SV.registerLayout('AdjoinTableGraph', {
sourcesPreprocess(sources, options, group) {
// let dataLength = sources.length;
// let tableHeadNodes = [];
// let nodeMap = {};
// let i;
// for (i = 0; i < dataLength; i++) {
// let graphNode = sources[i];
// tableHeadNodes.push({
// id: `table-head-node-${i}`,
// type: 'tableHeadNode',
// data: graphNode.id
// });
// nodeMap[graphNode.id] = {
// node: graphNode,
// order: i,
// neighbor: []
// };
// }
// Object.keys(nodeMap).map(key => {
// let nodeData = nodeMap[key],
// neighbor = nodeData.node.neighbor;
// if (neighbor === undefined) {
// return;
// }
// neighbor.forEach((item, index) => {
// let targetNodeData = nodeMap[item];
// nodeData.neighbor.push({
// id: `${key}-table-node-${item}`,
// type: 'tableNode',
// data: item.toString(),
// order: targetNodeData.order
// });
// targetNodeData.neighbor.push({
// id: `${item}-table-node-${key}`,
// type: 'tableNode',
// data: key.toString(),
// order: nodeData.order
// });
// });
// Object.keys(nodeMap).map(key => {
// let nodeData = nodeMap[key],
// neighbor = nodeData.neighbor;
// if (neighbor === undefined) {
// return;
// }
// neighbor.sort((n1, n2) => {
// return n1.order - n2.order;
// });
// for (let i = 0; i < neighbor.length; i++) {
// if (neighbor[i + 1]) {
// neighbor[i].next = `tableNode#${neighbor[i + 1].id}`;
// }
// }
// });
// tableHeadNodes.forEach(item => {
// let nodeData = nodeMap[item.data],
// neighbor = nodeData.neighbor;
// if (neighbor.length) {
// item.headNext = `tableNode#${neighbor[0].id}`;
// }
// });
// });
// sources.push(...tableHeadNodes);
// Object.keys(nodeMap).map(key => {
// let nodeData = nodeMap[key],
// neighbor = nodeData.neighbor;
// sources.push(...neighbor);
// });
// return sources;
},
defineOptions() {
return {
element: {
default: {
type: 'circle',
label: '[id]',
size: 40,
style: {
stroke: '#333',
fill: '#95e1d3'
}
},
tableHeadNode: {
type: 'two-cell-node',
label: '[data]',
size: [70, 40],
style: {
stroke: '#333',
fill: '#95e1d3'
}
},
tableNode: {
type: 'link-list-node',
label: '[data]',
size: [60, 30],
style: {
stroke: '#333',
fill: '#95e1d3'
}
}
},
link: {
neighbor: {
style: {
stroke: '#333'
}
},
headNext: {
sourceAnchor: 1,
targetAnchor: 6,
style: {
stroke: '#333',
endArrow: {
path: G6.Arrow.triangle(8, 6, 0),
fill: '#333'
},
startArrow: {
path: G6.Arrow.circle(2, -1),
fill: '#333'
}
}
},
next: {
sourceAnchor: 2,
targetAnchor: 6,
style: {
stroke: '#333',
endArrow: {
path: G6.Arrow.triangle(8, 6, 0),
fill: '#333'
},
startArrow: {
path: G6.Arrow.circle(2, -1),
fill: '#333'
}
}
}
},
layout: {
radius: 150,
interval: 250,
xInterval: 50,
yInterval: 50
},
behavior: {
dragNode: ['default', 'tableNode']
}
};
},
/**
* 对子树进行递归布局
* @param node
* @param parent
*/
layoutItem(node, prev, layoutOptions) {
if (!node) {
return null;
}
let width = node.get('size')[0];
if (prev) {
node.set('y', prev.get('y'));
node.set('x', prev.get('x') + layoutOptions.xInterval + width);
}
if (node.next) {
this.layoutItem(node.next, node, layoutOptions);
}
},
layout(elements, layoutOptions) {
let nodes = elements.filter(item => item.type === 'default'),
tableHeadNode = elements.filter(item => item.type === 'tableHeadNode'),
nodeLength = nodes.length,
{ radius } = layoutOptions,
intervalAngle = 2 * Math.PI / nodes.length,
i;
for (i = 0; i < nodeLength; i++) {
let [x, y] = Vector.rotation(-intervalAngle * i, [0, -radius]);
nodes[i].set({ x, y });
}
const tableY = -radius,
tableX = radius + 20;
for (i = 0; i < tableHeadNode.length; i++) {
let node = tableHeadNode[i],
height = node.get('size')[1];
node.set({
x: tableX,
y: tableY + node.get('y') + i * height
});
if (node.headNext) {
let y = node.get('y') + height - node.headNext.get('size')[1],
x = tableX + layoutOptions.xInterval * 2.5;
node.headNext.set({ x, y });
this.layoutItem(node.headNext, null, layoutOptions);
}
}
}
});