g6/demos/others-tree-bubble-leaves.html
2020-02-14 11:30:12 +08:00

309 lines
7.0 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Dagre Layout</title>
</head>
<style>
.g6-tooltip {
border: 1px solid #e2e2e2;
border-radius: 4px;
font-size: 12px;
color: #545454;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px 8px;
box-shadow: rgb(174, 174, 174) 0px 0px 10px;
}
</style>
<body>
<div id="mountNode"></div>
<script src="../build/dagre.js"></script>
<script src="../build/g6.js"></script>
<script>
const data = {
nodes: [
{
id: '1',
label: '1',
},
{
id: '2',
label: '2',
},
{
id: '3',
label: '3',
},
{
id: '4',
label: '4',
},
{
id: '5',
label: '5',
},
{
id: '6',
label: '6',
},
{
id: '7',
label: '7',
},
{
id: '8',
label: '8',
isLeaf: true,
},
{
id: '9',
label: '9',
isLeaf: true,
},
{
id: '10',
label: '10',
isLeaf: true,
},
{
id: '11',
label: '11',
isLeaf: true,
},
{
id: '12',
label: '12',
isLeaf: true,
},
{
id: '13',
label: '13',
isLeaf: true,
},
{
id: '14',
label: '14',
isLeaf: true,
},
{
id: '15',
label: '15',
isLeaf: true,
},
{
id: '16',
label: '16',
isLeaf: true,
},
{
id: '17',
label: '17',
isLeaf: true,
},
{
id: '18',
label: '18',
isLeaf: true,
},
{
id: '19',
label: '19',
isLeaf: true,
},
],
edges: [
{
source: '1',
target: '2',
},
{
source: '1',
target: '3',
},
{
source: '3',
target: '4',
},
{
source: '2',
target: '5',
},
{
source: '5',
target: '6',
},
{
source: '5',
target: '7',
},
{
source: '7',
target: '8',
},
{
source: '6',
target: '9',
},
{
source: '6',
target: '10',
},
{
source: '6',
target: '11',
},
{
source: '6',
target: '12',
},
{
source: '6',
target: '13',
},
{
source: '6',
target: '14',
},
{
source: '4',
target: '15',
},
{
source: '4',
target: '16',
},
{
source: '4',
target: '17',
},
{
source: '4',
target: '18',
},
{
source: '4',
target: '19',
},
],
};
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 700,
modes: {
default: ['drag-node', 'drag-canvas'],
},
defaultNode: {
shape: 'rect', // hexagon
color: 'steelblue',
},
defaultEdge: {
style: {
stroke: '#aaa',
},
},
});
const nodes = data.nodes;
const edges = data.edges;
const nodeMap = new Map();
const branchNodes = [];
const branchEdges = [];
const leafGroups = {};
const branchNodesMap = new Map();
const leafGroupOffset = 100;
// separate the leaves and branch nodes
nodes.forEach((node, i) => {
nodeMap.set(node.id, node);
if (node.isLeaf) {
node.size = 30;
node.shape = 'circle';
edges.forEach(edge => {
if (edge.source === node.id) {
node.parent = edge.target;
} else if (edge.target === node.id) {
node.parent = edge.source;
}
});
if (!leafGroups[node.parent]) leafGroups[node.parent] = [];
leafGroups[node.parent].push(node);
} else {
branchNodes.push(node);
branchNodesMap.set(node.id, node);
}
});
edges.forEach(edge => {
if (
branchNodesMap.get(edge.source) !== undefined &&
branchNodesMap.get(edge.target) !== undefined
) {
branchEdges.push(edge);
}
});
// layout the nodes with isLeaf === false by dagre
const dagreLayout = new G6.Layout['dagre']({
nodesep: 50,
ranksep: 10,
});
dagreLayout.init({ nodes: branchNodes, edges: branchEdges });
dagreLayout.execute();
//layout the leaves with isLeaf === true by force
const forceLayoutsMap = new Map();
Object.keys(leafGroups).forEach(function(parentId) {
const lg = leafGroups[parentId];
const parent = branchNodesMap.get(parentId);
const center = [parent.x, parent.y + leafGroupOffset];
const forceLayout = new G6.Layout['force']({
center,
linkDistance: 0,
nodeStrength: 30,
collideStrength: 0.7,
alphaDecay: 0.01,
preventOverlap: true,
tick: () => {
graph.refreshPositions();
},
});
forceLayout.init({ nodes: lg, edges: [] });
forceLayout.execute();
forceLayoutsMap.set(parentId, forceLayout);
});
graph.positionsAnimate();
graph.data(data);
graph.render();
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
graph.on('node:dragstart', e => {
const model = e.item.get('model');
if (model.isLeaf) {
const layoutMethod = forceLayoutsMap.get(model.parent);
layoutMethod.ticking = false;
layoutMethod.forceSimulation.stop();
layoutMethod.execute();
refreshDragedNodePosition(e);
}
});
graph.on('node:drag', e => {
const model = e.item.get('model');
if (model.isLeaf) {
refreshDragedNodePosition(e);
}
});
graph.on('node:dragend', e => {
const model = e.item.get('model');
if (model.isLeaf) {
e.item.get('model').fx = null;
e.item.get('model').fy = null;
}
});
</script>
</body>
</html>