g6/demos/expandfixnodes-layout.html

658 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</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};
const ForceLayoutPlugin = new Force({
center: [ 500, 300 ], // 向心力作用点
nodeStrength: -10, // 节点作用力
preventOverlap: true, // 是否防止节点相互覆盖
nodeRadius: 40, // 节点半径
edgeStrength: 1, // 边的作用力, 默认为根据节点的入度出度自适应
linkDistance: 100, // 默认边长度
forceSimulation: null, // 自定义 force 方法
});
// 封装点击添加边的交互
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);
});
console.log(newNodeModels);
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;
}
});
// them add it into graph
if (!exist) {
// set the initial positions of the new nodes to 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());
});
ForceLayoutPlugin.updateLayout( {'nodeStrength': -10, 'data': {'nodes': allNodeModels, 'edges': allEdgeModels}});
}
});
let data = getNodeById.data;
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 600,
plugins: [ ForceLayoutPlugin ],
modes: {
default: ['drag-node', 'click-select', 'click-add-node']
},
defaultNode: {
size: [40, 40],
color: 'steelblue'
},
defaultEdge: {
size: 1,
color: '#e2e2e2'
},
nodeStyle: {
default: {
lineWidth: 2,
fill: '#fff'
},
selected: {
fill: 'steelblue'
}
},
edgeStyle: {
default: {
endArrow: {
path: 'M 4,0 L -4,-4 L -4,4 Z',
d: 4
}
}
}
});
graph.data(data);
ForceLayoutPlugin.layout(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>