g6/demos/layout-expand-nodes.html
2019-10-10 20:01:23 +08:00

638 lines
18 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Expand Nodes with Force Layout</title>
</head>
<body>
<div id="mountNode"></div>
<script src="../build/g6.js"></script>
<script src="../build/force.js"></script>
<script src="./assets/d3-4.13.0.min.js"></script>
<script>
const getNodeById = {
"success": true,
"data": {
"nodes": [{
"id": "20",
"nodeType": "Person",
"label": "name1",
"properties": {
"age": "37",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "M",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "name1",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1",
"nodeType": "Person",
"label": "name2",
"properties": {
"age": "31",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "FM",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "name2",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
}],
"edges": [{
"source": "20",
"target": "1"
}],
"queryResult": "",
"graphView": true
},
"errorCode": null,
"msg": null
}
// 根据节点扩展
const getNodesByNodeId = {
"success": true,
"data": {
"nodes": [{
"id": "20",
"nodeType": "Person",
"label": "祁同伟",
"properties": {
"age": "37",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "M",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "祁同伟",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "22",
"nodeType": "Person",
"label": "高晓秦",
"properties": {
"age": "23",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "高晓秦",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "10",
"nodeType": "Person",
"label": "高育良",
"properties": {
"age": "57",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "M",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "高育良",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "12",
"nodeType": "Person",
"label": "高晓凤",
"properties": {
"age": "22",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "高晓凤",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "21",
"nodeType": "Person",
"label": "梁璐",
"properties": {
"age": "40",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "梁璐",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "11",
"nodeType": "Person",
"label": "吴淑芬",
"properties": {
"age": "50",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "吴淑芬",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "100",
"nodeType": "Enterprise",
"label": "小米",
"properties": {
"IsChineseFunded": "",
"businessScope": "",
"credit": "",
"employeesNumber": "0",
"enterpriseNature": "",
"establishmentTime": "",
"holdingType": "",
"importExportRightMark": "",
"industryType": "",
"isAdvantageEnterprise": "",
"isLeadingEnterprise": "",
"isOnBlacklist": "",
"isOvercapacity": "",
"isRegionalKeyEnterprise": "",
"isSangaoEnterprise": "",
"name": "小米",
"registeredCapital": "0",
"registrationAddress": "",
"sbh": "",
"size": "",
"stockCode": "",
"telephone": ""
}
},
{
"id": "102",
"nodeType": "Enterprise",
"label": "茅台",
"properties": {
"IsChineseFunded": "",
"businessScope": "",
"credit": "",
"employeesNumber": "0",
"enterpriseNature": "",
"establishmentTime": "",
"holdingType": "",
"importExportRightMark": "",
"industryType": "",
"isAdvantageEnterprise": "",
"isLeadingEnterprise": "",
"isOnBlacklist": "",
"isOvercapacity": "",
"isRegionalKeyEnterprise": "",
"isSangaoEnterprise": "",
"name": "茅台",
"registeredCapital": "0",
"registrationAddress": "",
"sbh": "",
"size": "",
"stockCode": "",
"telephone": ""
}
}],
"edges": [{
"target": "100",
"source": "20"
},
{
"target": "102",
"source": "20"
},
{
"target": "10",
"source": "20"
},
{
"target": "11",
"source": "20"
},
{
"target": "21",
"source": "20"
},
{
"target": "21",
"source": "20"
},
{
"target": "22",
"source": "20"
},
{
"target": "11",
"source": "10",
},
{
"target": "12",
"source": "10"
},
{
"target": "22",
"source": "21",
},
{
"target": "22",
"source": "12"
}],
"queryResult": "",
"graphView": true
},
"errorCode": null,
"msg": null
}
// 根据节点扩展
const getNodesByNodeId2 = {
"success": true,
"data": {
"nodes": [{
"id": "22",
"nodeType": "Person",
"label": "高晓秦",
"properties": {
"age": "23",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "高晓秦",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1000",
"nodeType": "Person",
"label": "晓秦1",
"properties": {
"age": "57",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "M",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "晓秦1",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1001",
"nodeType": "Person",
"label": "晓秦2",
"properties": {
"age": "22",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "晓秦2",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1002",
"nodeType": "Person",
"label": "晓秦3",
"properties": {
"age": "40",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "晓秦3",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1003",
"nodeType": "Person",
"label": "晓秦4",
"properties": {
"age": "40",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "晓秦4",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
},
{
"id": "1004",
"nodeType": "Person",
"label": "晓秦5",
"properties": {
"age": "40",
"annualIncome": "0",
"career": "",
"credit": "",
"education": "",
"email": "",
"gender": "F",
"highestEducation": "",
"isBusiness": "",
"isOnBlacklist": "",
"name": "晓秦5",
"permanentResidenceAddress": "",
"residentialAddress": "",
"sbh": "",
"telephone": "",
"workUnit": ""
}
}],
"edges": [{
"target": "22",
"source": "1000"
},
{
"target": "22",
"source": "1001"
},
{
"target": "22",
"source": "1002"
},
{
"target": "1001",
"source": "1002"
},
{
"target": "1000",
"source": "1"
},
{
"target": "20",
"source": "1002"
},
{
"target": "22",
"source": "1003"
},
{
"target": "22",
"source": "1004"
}],
"queryResult": "",
"graphView": true
},
"errorCode": null,
"msg": null
}
let clickedNodeId = -1;
let clickedNodePos = {
'x': 500,
'y': 300
};
// 封装点击添加边的交互
G6.registerBehavior('click-add-node', {
getEvents() {
return {
'node:click': 'onClick'
};
},
onClick(ev) {
const itemModel = ev.item.getModel();
clickedNodeId = itemModel.id;
clickedNodePos.x = itemModel.x;
clickedNodePos.y = itemModel.y;
const graph = this.graph;
const nodes = graph.getNodes();
const edges = graph.getEdges();
let newData = getNodeById.data;
if (itemModel.id == 20) newData = getNodesByNodeId.data;
else if (itemModel.id == 22) newData = getNodesByNodeId2.data;
let newNodeModels = newData.nodes;
let newEdgeModels = newData.edges;
let allNodeModels = [],
allEdgeModels = [];
// fix the existing nodes by set the fx and fy to the current value
// to cancel the fix the node, set fx = null fy = null
nodes.forEach((n, i) => {
const model = n.getModel();
model.fixed = true;
model.fx = model.x;
model.fy = model.y;
allNodeModels.push(model);
});
newNodeModels.forEach((nodeModel, i) => {
// if it does not exist in nodes
let exist = false;
nodes.forEach((n, i) => {
if (n.getModel().id == nodeModel.id) {
exist = true;
return;
}
});
// then add it into graph
if (!exist) {
// set the initial positions of the new nodes at the clicked node
nodeModel.x = itemModel.x;
nodeModel.y = itemModel.y;
const node = graph.addItem('node', nodeModel);
allNodeModels.push(nodeModel);
nodes.push(node);
}
});
newEdgeModels.forEach((em, i) => {
// if it does not exist in nodes
let exist = false;
edges.forEach((e, i) => {
const eModel = e.getModel();
if (eModel.source == em.source && eModel.target == em.target) {
exist = true;
return;
}
});
if (!exist) {
const edge = graph.addItem('edge', em);
edges.push(edge);
}
});
edges.forEach((e, i) => {
allEdgeModels.push(e.getModel());
});
graph.changeData({
nodes: allNodeModels,
edges: allEdgeModels
});
}
});
let data = getNodeById.data;
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 600,
layout: {
type: 'force',
center: [500, 300],
// 向心力作用点
nodeStrength: -30,
// 节点作用力
preventOverlap: true,
// 是否防止节点相互覆盖
nodeSize: 40,
// 节点大小 / 直径
edgeStrength: 0.1,
// 边的作用力, 默认为根据节点的入度出度自适应
linkDistance: 100,
// 默认边长度
},
modes: {
default: ['drag-node', 'click-select', 'click-add-node']
},
defaultNode: {
size: [40, 40],
color: 'steelblue'
},
defaultEdge: {
size: 1,
color: '#e2e2e2'
}
});
graph.data(data);
graph.render();
graph.on('node:dragend', ev => {
const itemModel = ev.item.getModel();
itemModel.fixed = true;
itemModel.fx = ev.x;
itemModel.fy = ev.y;
});
</script>
</body>
</html>