let container = document.getElementById("mynetwork");
let data = {
nodes: this.nodes,
edges: this.edges,
};
let options = {interaction: { hover: true }};
network = new vis.Network(container, data, options);
// 事件监听
this.networkEvent();
},
// 拓扑网络监听事件
networkEvent() {
//单击
network.on("click", (e) => {});
// 双击
network.on("doubleClick", (e) => {});
// 单击鼠标右键
network.on("oncontext", (e) => {});
// 节点悬停
network.on("hoverNode", (e) => {});
// 节点失焦
network.on("blurNode", (e) => {});
// 边悬停
network.on("hoverEdge", (e) => {});
// 边失焦
network.on("blurEdge", (e) => {});
// 鼠标拖动开始事件
network.on("dragStart", (e) => {});
// 鼠标拖动结束事件
network.on("dragEnd", (e) => {});
// 鼠标缩放事件
network.on("zoom", (e) => {});
//...
}
需求:展开节点,收缩节点,收缩展开过的节点光晕颜色改变(区别未展开过的节点)
DataSet Methods
新增节点/边:nodes.add({…}),edges.add({…})
删除节点/边:nodes.remove({…}),edges.remove({…})
<template>
<div id="mynetwork" class="mynetwork2">div>
template>
<script>
const vis = require("vis-network/dist/vis-network.min.js");
import _ from "lodash";
var network = null;
export default {
data() {
return {
//创建节点对象
nodes: new vis.DataSet([
{
id: "node-1",
label: "Node 1",
title: "1111",
image: {
selected: require("@/assets/people-opened.png"),
unselected: require("@/assets/people-def.png"),
},
},
]),
//创建连线对象
edges: new vis.DataSet([
// { id: "edge-1", from: "node-1", to: "node-2" },
]),
removeNodes: [],
removeEdges: [],
};
},
mounted() {
this.initNetwork();
},
methods: {
// 初始化网络拓扑
initNetwork() {
let container = document.getElementById("mynetwork");
let data = {
nodes: this.nodes,
edges: this.edges,
};
let options = {
interaction: {
hover: true,
},
layout: {
randomSeed: 2, //配置每次生成的节点位置都一样,参数为数字1、2等
},
nodes: {
// shape: "dot",
// shape: "circularImage",
// borderWidth: 2,
shape: "image",
size: 23,
color: {
// border: "rgba(255, 255, 255, 1)",
background: "rgba(102, 51, 255, 1)",
},
font: {
// color: "#fff",
},
shadow: {
enabled: true,
// color: "rgba(153, 102, 204, 1)",
color: "rgba(153, 0, 204, 1)",
size: 40,
x: 0,
y: 0,
},
chosen: {
label: false,
// node: function(values, id, selected, hovering) {
node: function(values) {
values.shadowColor = "rgba(255, 215, 0, 0.8)";
},
},
// shapeProperties: {
// borderDashes: [5, 15],
// },
},
edges: {
hoverWidth: 0,
shadow: true,
arrows: {
to: {
enabled: true,
type: "arrow",
},
},
color: {
color: "#525A81",
highlight: "#FFBA30",
hover: "#FFBA30",
// inherit: "from",
opacity: 1.0,
},
font: {
// color: "#fff",
size: 12, // px
strokeWidth: 0, // px
},
},
physics: {
enabled: true,
// minVelocity: 1 //(default: 1)一旦达到所有节点的最小速度,我们假设网络已经稳定,布局停止。
timestep: 0.2,
// wind: {
// x: 10,
// y: 10
// }
},
};
network = new vis.Network(container, data, options);
// 事件监听
this.networkEvent();
},
// 拓扑网络监听事件
networkEvent() {
// 单击
network.on("click", (e) => {
console.log("单击:", e);
console.log(this.edges.get(e.edges[0]));
// 只有在点击节点时才进行节点的增删
if (!e.nodes.length) {
return false;
}
var clickNodeList = this.nodes.get(e.nodes[0]);
console.log(clickNodeList);
if (!clickNodeList.open) {
// 恢复过滤数据
// this.recoverFilterData();
this.generateData(e.nodes[0], e.edges[0], e.nodes[0]);
// 判断是否有子节点
let haschildState = network.getConnectedNodes(e.nodes[0], "to").length ? true : false;
this.nodes.update({
id: e.nodes[0],
open: true,
haschildren: haschildState,
changEdge: e.edges[0],
});
if (e.edges[0]) {
this.edges.update({
id: e.edges[0],
open: true,
haschildren: haschildState,
// length: 600,
});
}
// 移动焦点到视图中心
// 双击某一节点,画布放大至1:1比例,当前节点处于画布中心位置
var option = {
scale: 1.0,
offset: { x: 0, y: 0 },
animation: {
duration: 1000,
easingFunction: "easeInOutQuad",
},
};
network.focus(e.nodes[0], option);
} else {
// 获取该节点下 未展开的节点的集合 和 从该节点发出的到未展开节点线的集合
let nodeItems = this.nodes.get({
filter: function(item) {
return item.parentId === e.nodes[0] && !item.open && !item.haschildren;
},
});
// console.log("nodeItems", nodeItems);
let edgesItem = this.edges.get({
filter: function(item) {
return (
!item.open && item.from == e.nodes[0] && !item.haschildren
// (item.to == e.nodes[0] || item.from == e.nodes[0])
);
},
});
console.log("edgesItem", edgesItem);
// 需求: 只缩进当前节点一度关系中未展开的节点,一度关系点已展开关系的不缩进
// 缩进( 删除未展开子节点和子节点连线)
// this.addNew(this.removeNodes, nodeItems);
// this.addNew(this.removeEdges, edgesItem);
this.nodes.remove(nodeItems);
this.edges.remove(edgesItem);
// 判断是否有子节点
let haschildState = network.getConnectedNodes(e.nodes[0], "to").length ? true : false;
this.nodes.update({
id: e.nodes[0],
open: false,
shadow: {
// color: "rgba(166, 26, 120, 1)",
color: "rgba(81, 0, 255, 1)",
},
image: {
selected: require("@/assets/people-opened.png"),
unselected: require("@/assets/people-def.png"),
},
// clickNodeList.image.selected || clickNodeList.image, //已修改后的字段为image
haschildren: haschildState,
});
if (clickNodeList.changEdge) {
// 初始中心节点无changEdge
this.edges.update({
id: clickNodeList.changEdge,
open: false,
haschildren: haschildState,
// length: 280,
});
}
}
});
},
generateData(nodename, edgename, orgnode) {
var len = 2;
let nodes = [];
let edges = [];
let nodeName = nodename || "node";
let edgeName = edgename || "edge";
const relation = ["诈骗","父亲","母亲","哥哥","姐姐","同事","定向扩展","妻子","弟弟",];
const labelType = ["people", "car", "phone", "qq", "wx", "email"];
for (var i = 1; i <= len; i++) {
const randomIndex = Math.floor(Math.random() * 6);
nodes.push({
parentId: orgnode,
id: nodeName + "-" + i,
label: labelType[randomIndex],
shape: "image",
image: {
selected: require("@/assets/people-opened.png"),
unselected: require("@/assets/people-def.png"),
},
haschildren: false,
});
edges.push({
id: edgeName + "-" + i,
from: orgnode || "node-1",
to: nodeName + "-" + i,
label: relation[Math.floor(Math.random() * 10)],
haschildren: false,
});
}
// 避免添加重复数据导致错误
this.buildData(nodes, edges);
},
// 构建数据
buildNode(nodes) {
nodes.forEach((item) => {
// var node = {
// ...
//};
this.nodes.add(item);
});
// console.log("---------", this.nodes.get());
},
buildEdge(edges) {
edges.forEach((item) => {
// var edge = {
// ...
// };
this.edges.add(item);
});
},
buildData(n, e) {
// 去重
// console.log(this.nodes.get());
// 删除n中与第二个数组对象id相同的值
let differenceN = _.differenceBy(n, this.nodes.get(), "id");
let differenceE = _.differenceBy(e, this.edges.get(), "id");
// console.log("differenceN:", differenceN, differenceE);
this.buildNode(differenceN);
this.buildEdge(differenceE);
},
addNew(arr, newarr) {
for (const item of newarr) {
arr.push(item);
}
},
recoverFilterData() {
// console.log("reset:", this.removeNodes);
// console.log("reset:", this.removeEdges);
},
},
};
script>
<style scoped>
.mynetwork2 {
height: 100%;
/* background-color: #2a004a; */
}
style>
效果如下
功能点:
右键展开菜单,点击请求节点数据,或展开下级菜单
拖动节点或画布,菜单跟随节点
缩放画布,菜单同步缩放
对其它或者空白区域进行操作时,关闭菜单