feat: 优化了index文本配置方式

This commit is contained in:
黎智洲
2021-08-30 23:57:05 +08:00
parent 8d8f007237
commit e155269533
11 changed files with 509 additions and 129 deletions
+128
View File
@@ -0,0 +1,128 @@
const isNeighbor = 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;
}
if (neighborB && neighborB.includes(itemA.id)) {
return true;
}
return false;
}
SV.registerLayouter('AdjoinMatrixGraph', {
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].id : undefined,
indexLeft: i % dataLength === 0? sources[i / dataLength].id : 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 && isNeighbor(itemI, itemJ)) {
matrixNodes[i * dataLength + j].data = 1;
}
}
}
sources.push(...matrixNodes);
return sources;
},
defineOptions() {
return {
element: {
default: {
type: 'circle',
label: '[id]',
size: 40,
style: {
stroke: '#333',
fill: '#95e1d3'
}
},
matrixNode: {
type: 'indexed-node',
label: '[data]',
size: [40, 40],
style: {
stroke: '#333',
fill: '#95e1d3'
},
indexOptions: {
indexTop: { position: 'top' },
indexLeft: { position: 'left' }
}
}
},
link: {
neighbor: {
style: {
stroke: '#333'
}
}
},
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 });
}
}
});
+236
View File
@@ -0,0 +1,236 @@
SV.registerLayouter('AdjoinTableGraph', {
sourcesPreprocess(sources, options) {
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);
}
}
}
});
+5 -1
View File
@@ -19,11 +19,15 @@ SV.registerLayouter('Array', {
element: {
default: {
type: 'indexed-node',
label: '[data]',
label: '[id]',
size: [60, 30],
style: {
stroke: '#333',
fill: '#95e1d3'
},
indexOptions: {
index: { position: 'bottom' },
indexTop: { position: 'top' }
}
}
},
-1
View File
@@ -130,4 +130,3 @@ SV.registerLayouter('ChainHashTable', {
-9
View File
@@ -10,12 +10,6 @@ SV.registerLayouter('Stack', {
delete stackBottomNode.external;
}
if(options.layout.indexPosition) {
sources.forEach(item => {
item.indexPosition = options.layout.indexPosition;
});
}
return sources;
},
@@ -55,9 +49,6 @@ SV.registerLayouter('Stack', {
}
}
},
layout: {
indexPosition: 'left'
},
behavior: {
dragNode: false
}
+10 -23
View File
@@ -75,6 +75,8 @@
<script src="./Layouter/Array.js"></script>
<script src="./Layouter/HashTable.js"></script>
<script src="./Layouter/LinkStack.js"></script>
<script src="./Layouter/AdjoinMatrixGraph.js"></script>
<script src="./Layouter/AdjoinTableGraph.js"></script>
<script>
@@ -88,34 +90,19 @@
let data = [{
"LinkStack1": {
"g1": {
"data": [
{
"id": 0,
external: 'gg'
}
{ id: 0, neighbor: [4, 3] }, { id: 1, neighbor: [0, 3] }, { id: 2, neighbor: [4, 0] },
{ id: 3, neighbor: [5, 2] }, { id: 4 },
{ id: 5, neighbor: [0, 1] }
],
"layouter": "LinkStack"
}
}, {
"LinkStack1": {
"data": [
{
"id": 0
},
{
"id": 1,
"freed": true,
},
{
"freed": true,
"id": 2
}
],
"layouter": "LinkStack"
// "layouter": "AdjoinTableGraph"
"layouter": "AdjoinMatrixGraph"
}
}];
let dataIndex = 0,
curData = data[dataIndex];