用vis实现网络拓扑图
2022-07-02 本文已影响0人
江湖小盛
需求背景:
1、实现一个网络拓扑图的可视化界面
2、能和后台数据进行动态绑定渲染
3、实现交互功能(拖拽、放大缩小、悬停提示等)
安装&使用
在项目中引入 vis有以下两种方式:NPM 引入和CDN 引入。
1、在项目中使用 NPM 包引入
step1: 安装vis到项目
npm install vis --save
step2: 在js文件或者vue文件中引入vis
import vis from vis
2、在 HTML 中使用 CDN 引入
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
快速入门
创建一个vis 的拓扑图图仅需要下面几个步骤:
1、创建关系图的 HTML 容器
2、数据准备
3、获取容器
4、初始化拓扑图
step1: 创建容器
需要在 HTML 中创建一个用于容纳 vis绘制的图的容器,并且为容器设置宽高, vis 在绘制时会在该容器下追加 canvas 标签,然后将图绘制在其中。
<style type="text/css">
#mynetwork {
width: 600px;
height: 400px;
}
</style>
<div id="mynetwork"></div>
step2: 数据准备
引入vis 的数据源为 JSON 格式的对象。该对象中需要有节点(nodes)和边(edges)字段,分别用数组表示:
// 创建节点数据数组
var nodesData= new vis.DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" }
]);
// 创建边数据数组
var edgesData= new vis.DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 },
{ from: 3, to: 3 }
]);
// 将数据赋值给vis 数据格式化器
var data = {
nodes: new vis.DataSet(nodesData),
edges: new vis.DataSet(edgesData)
};
var options = {};
注意:
- nodes 数组中包含节点对象。每个节点对象中唯一的、必要的 id 以标识不同的节点.
- edges 数组中包含边对象。from和 to是每条边的必要属性,分别代表了该边的起始点 id 与 目标点 id
- options中可以定制化配置节点和边
step3: 获取容器
var container = document.getElementById('mynetwork');
step4: 初始化拓扑图
var network = new vis.Network(container, data, options);
节点部分配置
1、节点形状、大小、缩放
nodes: {
shape: 'dot',
size: 20,
scaling: {
min: 10,
max: 5,
label:true
},
}
注意:定义节点的外观。有两种类型的节点
- 一类是标签在节点内部: ellipse, circle, database, box, text
- 另一类是标签在节点下面: image, circularImage, diamond, dot, star, triangle, triangleDown, hexagon, square和 icon。
- size 配置只适用于标签在节点下面的形状。
- scaling 配置 标签在节点内部的,只有在启用标签缩放时才会有效
- 使用缩放时,将忽略大小选项
下图是节点形状汇总:
节点形状.png
2、节点部分样式配置
nodes: {
font: { // 设置字体
color: '#000',
size: 16,
},
borderWidth: 1, // 节点边框的宽度
borderWidthSelected: 3, , // 节点被选中时边框的宽度
color: {
border: '#2B7CE9', // 节点边框颜色
background: '#97C2FC', // 节点背景色
hover: { // 节点鼠标滑过时状态颜色
border: 'blue',
background: '#D2E5FF'
}
},
shadow: true, // 节点阴影
fixed: false, // 拖拽节点是否可移动,true,不可移动。
}
边部分配置
1、边的箭头配置
edges: {
arrows: {
to: { // 指向目标点的箭头
enabled: true,
type: "arrow"
},
from: { // 指向起始点的箭头
enabled: true,
type: "arrow"
}
},
}
2、边的线条配置
edges: {
smooth: {
enabled: true, // 打开和关闭平滑曲线
type: "cubicbezier", // 线条类型
roundness: 0.2 // 线条平滑度
forceDirection:'horizontal' // 用于分层布局的配置项
},
hoverWidth: 2 //悬停于线条上的宽度
}
注意:
- type可能的选项: dynamic, continuous, discrete, diagonalCross, straightCross, horizontal, vertical, curvedCW, curvedCCW, cubicBezier。
- forceDirection选项仅用于cubicbezier曲线
布局配置
layout: {
improvedLayout: true, // 关系图将使用‘’Kamada Kawai‘’算法进行初始布局
clusterThreshold: 150, // 集群阈值
hierarchical: { // 层次布局
enabled: true,
direction: 'UD', // UD, DU, LR, RL
sortMethod: 'hubsize', // hubsize, directed
shakeTowards: 'leaves' // roots, leaves
}
}
交互配置
interaction:{
dragNodes:true,
dragView: true,
hover: true,
hoverConnectedEdges: true,
zoomView: true
}
简易demo
<!DOCTYPE html>
<html lang="en">
<head>
<title>Network</title>
<script type="text/javascript" src="./js/vis-network.min.js"></script>
<style type="text/css">
#mynetwork {
width: 600px;
height: 600px;
border: 1px solid lightgray;
}
</style>
</head>
<body>
<div id="mynetwork"></div>
<script type="text/javascript">
var nodesData = [
{ id: 0, label: "Node 0"},
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" },
{ id: 6, label: "Node 6" },
{ id: 7, label: "Node 7" },
{ id: 8, label: "Node 8" },
{ id: 9, label: "Node 9" },
{ id: 10, label: "Node 10" },
{ id: 11, label: "Node 11" },
{ id: 12, label: "Node 12" },
{ id: 13, label: "Node 13" },
{ id: 14, label: "Node 14" },
]
var edgesData = [
{ from: 0, to: 1, label: '数值:1' },
{ from: 0, to: 6, label: '数值:1' },
{ from: 0, to: 13, label: '数值:1' },
{ from: 0, to: 11, label: '数值:1' },
{ from: 1, to: 2, label: '数值:1' },
{ from: 2, to: 3, label: '数值:1' },
{ from: 2, to: 4, label: '数值:1' },
{ from: 3, to: 5, label: '数值:1' },
{ from: 1, to: 10, label: '数值:1' },
{ from: 1, to: 7, label: '数值:1' },
{ from: 2, to: 8, label: '数值:1' },
{ from: 2, to: 9, label: '数值:1' },
{ from: 3, to: 14, label: '数值:1' },
{ from: 1, to: 12, label: '数值:1' }
]
// 获取容器
var container = document.getElementById('mynetwork');
// 将数据赋值给vis 数据格式化器
var data = {
nodes: new vis.DataSet(nodesData),
edges: new vis.DataSet(edgesData)
};
var options = {
// 节点配置
nodes: {
shape: 'dot',
font: {
color: '#000',
size: 16,
},
borderWidth: 1,
borderWidthSelected: 3,
color: {
border: '#2B7CE9',
background: '#97C2FC',
hover: {
border: 'blue',
background: '#D2E5FF'
}
},
shadow: true,
fixed: false,
scaling: {
min: 10,
max: 5,
label: true
},
// size: 30
},
// 边配置
edges: {
arrows: {
to: {
enabled: true,
type: "arrow"
}
},
smooth: {
enabled: true,
type: "curvedCW",
roundness: 0.2
},
hoverWidth: 2
},
interaction: {
hover: true,
hoverConnectedEdges: true,
},
// 布局
layout: {
improvedLayout: true,
hierarchical: {
direction: "LR",
sortMethod: 'directed', // directed hubsize
shakeTowards: 'roots', // roots leaves
}
},
};
// 初始化关系图
var network = new vis.Network(container, data, options);
</script>
</body>
</html>
demo.png