mirror of
https://gitee.com/antv/g6.git
synced 2024-12-04 20:59:15 +08:00
refactor(util): refactor radial layout method & add demo
This commit is contained in:
parent
cad47b4b25
commit
004cb3ce56
1224
demos/assets/hierarchy.js
Normal file
1224
demos/assets/hierarchy.js
Normal file
File diff suppressed because it is too large
Load Diff
151
demos/tree-graph.html
Normal file
151
demos/tree-graph.html
Normal file
@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="../test/unit/graph/tree-graph-spec.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
</style>
|
||||
<body>
|
||||
<select id="layout">
|
||||
<option value="dendrogram">基础树</option>
|
||||
<option value="compactBox">紧凑树</option>
|
||||
</select>
|
||||
<input type="checkbox" id="radial" /><label for="radial">环形布局</label>
|
||||
<div id="mountNode"></div>
|
||||
<script src="assets/hierarchy.js"></script>
|
||||
<script src="../build/g6.js"></script>
|
||||
<script>
|
||||
let currentLayout = 'dendrogram';
|
||||
let radial = false;
|
||||
const layouts = {
|
||||
dendrogram: function(data) {
|
||||
return Hierarchy.dendrogram(data, {
|
||||
direction: 'LR', // H / V / LR / RL / TB / BT
|
||||
nodeSep: 50,
|
||||
rankSep: 100
|
||||
})},
|
||||
compactBox: function(data) {
|
||||
return Hierarchy.compactBox(data, { direction: 'LR' });
|
||||
}
|
||||
};
|
||||
const graph = new G6.TreeGraph({
|
||||
container: 'mountNode',
|
||||
width: 500,
|
||||
height: 500,
|
||||
pixelRatio: 2,
|
||||
modes: {
|
||||
default: [{
|
||||
type: 'collapse-expand',
|
||||
onChange(item, collapsed) {
|
||||
const data = item.get('model').data;
|
||||
data.collapsed = collapsed;
|
||||
return true;
|
||||
}
|
||||
}, 'drag-canvas']
|
||||
},
|
||||
layout: layouts.dendrogram
|
||||
});
|
||||
const data = {
|
||||
isRoot: true,
|
||||
id: 'Root',
|
||||
children: [
|
||||
{
|
||||
id: 'SubTreeNode1',
|
||||
children: [
|
||||
{
|
||||
id: 'SubTreeNode1.1'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode1.2'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode2',
|
||||
children: [
|
||||
{
|
||||
id: 'SubTreeNode2.1'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode2.2',
|
||||
children: [
|
||||
{
|
||||
id: 'SubTreeNode1.2.1'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode1.2.2'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode1.2.3'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
id: 'SubTreeNode3'
|
||||
}, {
|
||||
id: 'SubTreeNode4'
|
||||
}, {
|
||||
id: 'SubTreeNode5'
|
||||
}, {
|
||||
id: 'SubTreeNode6'
|
||||
}, {
|
||||
id: 'SubTreeNode7',
|
||||
children: [
|
||||
{
|
||||
id: 'SubTreeNode3.1'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode3.2'
|
||||
},
|
||||
{
|
||||
id: 'SubTreeNode3.3'
|
||||
}
|
||||
]
|
||||
}, {
|
||||
id: 'SubTreeNode8'
|
||||
}, {
|
||||
id: 'SubTreeNode9'
|
||||
}, {
|
||||
id: 'SubTreeNode10'
|
||||
}, {
|
||||
id: 'SubTreeNode11'
|
||||
}
|
||||
]
|
||||
};
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
graph.fitView();
|
||||
document.getElementById('radial').addEventListener('change', e => {
|
||||
if (e.target.checked) {
|
||||
graph.set('layout', (data) => {
|
||||
data = layouts[currentLayout](data);
|
||||
G6.Util.radialLayout(data);
|
||||
return data;
|
||||
});
|
||||
graph.render();
|
||||
graph.fitView();
|
||||
} else {
|
||||
radial = false;
|
||||
graph.set('layout', layouts[currentLayout]);
|
||||
graph.render();
|
||||
graph.fitView();
|
||||
}
|
||||
});
|
||||
document.getElementById('layout').addEventListener('change', (e) => {
|
||||
const layout = e.target.value;
|
||||
if (currentLayout !== layout) {
|
||||
currentLayout = layout;
|
||||
graph.set('layout', layouts[currentLayout]);
|
||||
graph.render();
|
||||
if (radial) {
|
||||
G6.Util.radialLayout(graph, 'LR');
|
||||
}
|
||||
graph.fitView();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -124,7 +124,7 @@ module.exports = {
|
||||
x: data.x,
|
||||
y: data.y
|
||||
};
|
||||
if (!point.x || !point.y) {
|
||||
if (Util.isNil(point.x) || Util.isNil(point.y)) {
|
||||
const model = node.get('parent').get('model');
|
||||
point.x = model.x;
|
||||
point.y = model.y;
|
||||
|
@ -4,6 +4,16 @@
|
||||
*/
|
||||
|
||||
const MathUtil = require('./math');
|
||||
const BaseUtil = require('./base');
|
||||
|
||||
function traverse(data, fn) {
|
||||
if (fn(data) === false) {
|
||||
return;
|
||||
}
|
||||
BaseUtil.each(data.children, child => {
|
||||
traverse(child, fn);
|
||||
});
|
||||
}
|
||||
|
||||
const GraphicUtil = {
|
||||
getBBox(element, parent) {
|
||||
@ -30,12 +40,15 @@ const GraphicUtil = {
|
||||
maxY: rightBottom.y
|
||||
};
|
||||
},
|
||||
radialLayout(graph, layout) {
|
||||
traverseTree(data, fn) {
|
||||
if (typeof fn !== 'function') {
|
||||
return;
|
||||
}
|
||||
traverse(data, fn);
|
||||
},
|
||||
radialLayout(data, layout) {
|
||||
// 布局方式有 H / V / LR / RL / TB / BT
|
||||
const VERTICAL_LAYOUTS = [ 'V', 'TB', 'BT' ];
|
||||
const width = graph.get('width');
|
||||
const height = graph.get('height');
|
||||
const radius = Math.min(width, height);
|
||||
const min = {
|
||||
x: Infinity,
|
||||
y: Infinity
|
||||
@ -52,32 +65,31 @@ const GraphicUtil = {
|
||||
radScale = 'x';
|
||||
rScale = 'y';
|
||||
}
|
||||
graph.get('nodes').forEach(node => {
|
||||
const model = node.get('model');
|
||||
if (model.x > max.x) {
|
||||
max.x = model.x;
|
||||
let count = 0;
|
||||
this.traverseTree(data, node => {
|
||||
count++;
|
||||
if (node.x > max.x) {
|
||||
max.x = node.x;
|
||||
}
|
||||
if (model.x < min.x) {
|
||||
min.x = model.x;
|
||||
if (node.x < min.x) {
|
||||
min.x = node.x;
|
||||
}
|
||||
if (model.y > max.y) {
|
||||
max.y = model.y;
|
||||
if (node.y > max.y) {
|
||||
max.y = node.y;
|
||||
}
|
||||
if (model.y < min.y) {
|
||||
min.y = model.y;
|
||||
if (node.y < min.y) {
|
||||
min.y = node.y;
|
||||
}
|
||||
});
|
||||
const avgRad = Math.PI * 2 / graph.get('nodes').length;
|
||||
const avgRad = Math.PI * 2 / count;
|
||||
const radDiff = max[radScale] - min[radScale];
|
||||
graph.get('nodes').forEach(node => {
|
||||
const model = node.get('model');
|
||||
const radial = (model[radScale] - min[radScale]) / radDiff * (Math.PI * 2 - avgRad) + avgRad;
|
||||
const r = model[rScale] / max[rScale] * radius;
|
||||
model.x = r * Math.cos(radial);
|
||||
model.y = r * Math.sin(radial);
|
||||
this.traverseTree(data, node => {
|
||||
const radial = (node[radScale] - min[radScale]) / radDiff * (Math.PI * 2 - avgRad) + avgRad;
|
||||
const r = node[rScale];
|
||||
node.x = r * Math.cos(radial);
|
||||
node.y = r * Math.sin(radial);
|
||||
});
|
||||
graph.refreshPositions();
|
||||
graph.fitView();
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -441,7 +441,7 @@ describe('tree graph with layout', () => {
|
||||
graph.emit('node:click', { item: parent });
|
||||
}, 600);
|
||||
});
|
||||
const treeData = {
|
||||
/* const treeData = {
|
||||
isRoot: true,
|
||||
id: 'Root',
|
||||
children: [
|
||||
@ -535,5 +535,5 @@ describe('tree graph with layout', () => {
|
||||
graph.data(treeData);
|
||||
graph.render();
|
||||
G6.Util.radialLayout(graph, 'TB');
|
||||
});
|
||||
});*/
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user