g6/demos/change-view.html

213 lines
5.1 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>重新布局不改变视窗</title>
</head>
<body>
<button id='changeView'>改变布局</button>
<div id="mountNode"></div>
<script src="../build/g6.js"></script>
<script src="../build//grid.js"></script>
<script>
G6.registerBehavior('click-add-node', {
getEvents() {
return {
'node:click': 'onClick'
};
},
onClick(ev) {
const itemModel = ev.item.getModel();
clickedNodeId = itemModel.id;
const graph = this.graph;
const nodes = graph.getNodes();
const edges = graph.getEdges();
let newData;
if (itemModel.id == 2) {
newData = data2_m;
} else {
return;
}
let newNodeModels = newData.nodes;
let newEdgeModels = [];
// deduplication the items in newEdgeModels
newData.edges.forEach(e => {
let exist = false;
newEdgeModels.forEach(ne => {
if(ne.source === e.source && ne.target === e.target) exist = true;
});
if(!exist) {
newEdgeModels.push(e);
}
});
// for graph.changeData()
const allNodeModels = [];
const allEdgeModels = [];
// add new nodes to graph
const nodeMap = new Map();
nodes.forEach((n, i)=>{
const nModel = n.getModel();
nodeMap.set(nModel.id, i);
});
newNodeModels.forEach((nodeModel, i) => {
if (nodeMap.get(nodeModel.id) === undefined) {
// set the initial positions of the new nodes to the focus(clicked) node
nodeModel.x = itemModel.x;
nodeModel.y = itemModel.y;
const node = graph.addItem('node', nodeModel);
}
});
// add new edges to graph
const edgeMap = new Map();
edges.forEach((e, i)=>{
const eModel = e.getModel();
edgeMap.set(eModel.source+","+eModel.target, i);
});
const oldEdgeNum = edges.length;
newEdgeModels.forEach((em, i) => {
const exist = edgeMap.get(em.source+","+em.target);
if (exist === undefined) {
const edge = graph.addItem('edge', em);
edgeMap.set(em.source+","+em.target, oldEdgeNum+i);
}
});
edges.forEach((e, i) => {
allEdgeModels.push(e.getModel());
});
nodes.forEach((n, i) => {
allNodeModels.push(n.getModel());
});
// the max degree about foces(clicked) node in the newly added data
const maxDegree = 4;
// the max degree about foces(clicked) node in the original data
const oMaxDegree = 3;
const unitRadius = 40;
const focusNodeId = "2";
// re-place the clicked node far away the exisiting items
// along the radius from center node to it
const vx = itemModel.x - focusNode.x;
const vy = itemModel.y - focusNode.y;
const vlength = Math.sqrt(vx*vx+vy*vy);
const ideallength = unitRadius * maxDegree + mainUnitRadius * oMaxDegree;
itemModel.x = ideallength * vx / vlength + focusNode.x;
itemModel.y = ideallength * vy / vlength + focusNode.y;
const subRadialLayout = new Radial({
center: [ itemModel.x, itemModel.y ],
maxIteration: 200,
focusNode: "2",
unitRadius,
linkDistance: 180
});
graph.addPlugin(subRadialLayout);
// only layout the newly added part around the clicked node
subRadialLayout.layout(
{
'nodes': newNodeModels,
'edges': newEdgeModels
}
);
graph.changeData({"nodes": allNodeModels, "edges": allEdgeModels});
}
});
const grid = new Grid()
const graph = new G6.TreeGraph({
plugins: [grid],
container: 'mountNode',
width: 500,
height: 500,
defaultNode: {
size: [20, 20]
},
modes: {
default: [ 'drag-node', 'drag-canvas', {
type: 'collapse-expand',
onChange(item, collapsed) {
const data = item.getModel()
data.collapsed = collapsed
return true
}
} ]
},
nodeStyle: {
default: {
fill: '#40a9ff',
stroke: '#096dd9'
}
},
edgeStyle: {
default: {
stroke: '#A3B1BF'
}
},
defaultEdge: {
shape: 'cubic-horizontal'
},
layout: {
type: 'dendrogram',
nodeSep: 50,
rankSep: 100,
direction: 'LR'
}
});
let data = {
isRoot: true,
id: 'Root',
style: {
fill: 'red'
},
children: [
{
id: 'SubTreeNode1',
raw: {},
children: [
{
id: 'SubTreeNode1.1'
}
]
},
{
id: 'SubTreeNode2',
children: [
{
id: 'SubTreeNode2.1'
},
{
id: 'SubTreeNode2.2'
}
]
}
]
};
graph.data(data)
graph.render()
graph.fitView()
document.getElementById('changeView').addEventListener('click', (evt) => {
const matrix = G6.Util.clone(graph.get('group').getMatrix())
data.children.pop()
graph.changeData(data)
graph.get('group').setMatrix(matrix)
graph.paint()
})
</script>
</body>
</html>