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

146 lines
4.2 KiB
JavaScript

const isNeighborDAM = function(itemA, itemB) {
let neighborA = itemA.neighbor,
neighborB = itemB.neighbor;
if (neighborA === undefined && neighborB === undefined) {
return false;
}
if (neighborA && neighborA.includes(itemB.id)) {
return true;
}
return false;
}
SV.registerLayout('DirectedAdjoinMatrixGraph', {
sourcesPreprocess(sources) {
let dataLength = sources.length;
let matrixNodeLength = dataLength * dataLength;
let matrixNodes = [];
let i, j;
for (i = 0; i < matrixNodeLength; i++) {
matrixNodes.push({
id: `mn-${i}`,
type: 'matrixNode',
indexTop: i < dataLength ? sources[i].data : undefined,
indexLeft: i % dataLength === 0 ? sources[i / dataLength].data : undefined,
data: 0
});
}
for (i = 0; i < dataLength; i++) {
for (j = 0; j < dataLength; j++) {
let itemI = sources[i],
itemJ = sources[j];
if (itemI.id !== itemJ.id && isNeighborDAM(itemI, itemJ)) {
matrixNodes[i * dataLength + j].data = 1;
}
}
}
sources.push(...matrixNodes);
return sources;
},
defineOptions() {
return {
node: {
default: {
type: 'circle',
size: 40,
label: '[data]',
style: {
fill: '#95e1d3',
stroke: '#333',
cursor: 'pointer',
backgroundFill: '#ddd'
},
labelOptions: {
style: { fontSize: 16 }
}
},
matrixNode: {
type: 'array-node',
size: [40, 40],
label: '[data]',
style: {
fill: '#95e1d3',
stroke: '#333',
cursor: 'pointer',
backgroundFill: '#ddd'
},
labelOptions: {
style: { fontSize: 16 }
}
}
},
link: {
neighbor: {
type: 'line',
style: {
endArrow: 'default',
lineAppendWidth: 10,
lineWidth: 1.6,
stroke: '#333',
}
}
},
indexLabel: {
indexTop: {
position: 'top',
style: {
fill: '#bbb'
}
},
indexLeft: {
position: 'left',
style: {
fill: '#bbb'
}
}
},
addressLabel: {
style: {
fill: '#999'
}
},
layout: {
radius: 150,
interval: 250
},
behavior: {
dragNode: ['default']
}
};
},
layout(elements, layoutOptions) {
let nodes = elements.filter(item => item.type === 'default'),
matrixNodes = elements.filter(item => item.type === 'matrixNode'),
nodeLength = nodes.length,
matrixNodeLength = matrixNodes.length,
{ interval, radius } = layoutOptions,
intervalAngle = 2 * Math.PI / nodes.length,
matrixNodeSize = matrixNodes[0].get('size')[0],
i;
const matrixY = -radius,
matrixX = interval;
for (i = 0; i < nodeLength; i++) {
let [x, y] = Vector.rotation(-intervalAngle * i, [0, -radius]);
nodes[i].set({ x, y });
}
for (i = 0; i < matrixNodeLength; i++) {
let x = matrixX + (i % nodeLength) * matrixNodeSize,
y = matrixY + Math.floor(i / nodeLength) * matrixNodeSize;
matrixNodes[i].set({ x, y });
}
}
});