首先要加载vis
npm install vis --save
需要使用的组件中引入
import Vis from "vis";
初始化图谱
<!--width,height 画布的宽度,高度。 可以是百分比或像素,一般在dom元素上设置 -->
<div id="network_id" class="network" style="height: 500px;"></div>
data() {
return {
nodesArray: [], //节点数组
edgesArray: [] //关系线数组
}
},
mounted() {
// 初始化
let container = document.getElementById("network_id");
let data = { nodes: this.nodesArray, edges: this.edgesArray }
let options = {
autoResize: true, //网络将自动检测其容器的大小调整,并相应地重绘自身
locale: "cn", //语言设置:工具栏显示中文
// 设置节点样式
nodes: {
shape: "dot", //节点的外观。为circle时label显示在节点内,为dot时label显示在节点下方
margin: 5, //当形状设置为box、circle、database、icon、text;label的边距
widthConstraint: 100, //设置数字,将节点的最小和最大宽度设为该值,当值设为很小的时候,label会换行,节点会保持一个最小值,里边的内容会换行
borderWidth: 1, //节点边框宽度,单位为px
borderWidthSelected: 3, //节点被选中时边框的宽度,单位为px
labelHighlightBold: false, //确定选择节点时标签是否变为粗体
},
// 边线配置
edges: {
width: 1,
length: 200,
arrows: { to: true }, //箭头指向to
},
interaction: {
hover: true,
hoverConnectedEdges: true
},
//计算节点之前斥力,进行自动排列的属性
physics: {
enabled: true, //默认是true,设置为false后,节点将不会自动改变,拖动谁谁动。不影响其他的节点
maxVelocity: 20,
minVelocity: 0.1
}
};
let network = new Vis.Network(container, data, options);
},
完整代码
<template>
<div class="Vis">
<!--width,height 画布的宽度,高度。 可以是百分比或像素,一般在dom元素上设置 -->
<div id="network_id" class="network" style="height: 500px;"></div>
<!--节点悬停-->
<div class="menu" id="divHoverNode" style="display:none;"></div>
</div>
</template>
<script>
import Vis from "vis";
export default {
data() {
return {
// 节点数组
nodesArray: [
{
"type": "Project",
"label": "kernel_git_pcmoore_selinux",
"id": 3559072,
"releaseTime": "2006-08-22 12:00:00",
"licenses": [
"GPL-2.0",
"GPL"
],
"copyrights": [
{
"context": "Copyright (C) 1989, 1991 Free Software Foundation, Inc.",
"time": "1989, 1991",
"author": "Free Software Foundation, Inc.",
"integrity": 3
},
{
"context": "copyrighted by the Free Software",
"time": null,
"author": "Free Software",
"integrity": 2
}
],
"version": "v2.6.17.10",
"selfCompatibleRiskFlag": 0,
"selfComplianceRiskFlag": 1
},
{
"type": "File",
"label": "e1000_hw.h",
"id": 1774161,
"licenses": [
"GPL-2.0-or-later"
],
"copyrights": [
{
"context": "(c) 1999 - 2005 Intel Corporation. All rights reserved.",
"time": "1999 - 2005",
"author": "Intel Corporation",
"integrity": 3
}
],
"isStrongInfection": 1,
"selfCompatibleRisk": [
]
},
{
"type": "File",
"label": "e1000_hw.h",
"id": 1774156,
"licenses": [
"GPL-2.0-or-later"
],
"copyrights": [
{
"context": "(c) 1999 - 2006 Intel Corporation. All rights reserved.",
"time": "1999 - 2006",
"author": "Intel Corporation",
"integrity": 3
}
],
"isStrongInfection": 1,
"selfCompatibleRisk": [
]
},
{
"type": "File",
"label": "sm_statefuns.c",
"id": 1395911,
"licenses": [
"GPL-2.0-or-later"
],
"copyrights": [
{
"context": "Copyright IBM Corp. 2001, 2004",
"time": "2001, 2004",
"author": "IBM Corp",
"integrity": 3
}
],
"isStrongInfection": 1,
"selfCompatibleRisk": [
]
},
{
"type": "Project",
"label": "kernel_git_tytso_fscrypt",
"id": 3559116,
"releaseTime": "2006-08-22 12:00:00",
"licenses": [
"GPL-2.0",
"GPL"
],
"copyrights": [
{
"context": "Copyright (C) 1989, 1991 Free Software Foundation, Inc.",
"time": "1989, 1991",
"author": "Free Software Foundation, Inc.",
"integrity": 3
}
],
"version": "v2.6.17.10",
"selfCompatibleRiskFlag": 0,
"selfComplianceRiskFlag": 1
},
{
"type": "File",
"label": "skbuff.c",
"id": 3334544,
"licenses": [
"GPL-2.0-or-later"
],
"copyrights": [
],
"isStrongInfection": 1,
"selfCompatibleRisk": [
]
}
],
// 关系线数组
edgesArray:
[
{
"from": 1774161,
"label": "MATCH",
"to": 1774156,
"id": 5967581,
"type": 2,
"rlf": 0,
"rcf": 1,
"cf": 0
},
{
"from": 3559116,
"label": "CONTAIN",
"to": 1395911,
"id": 9763072,
"type": 0
},
{
"from": 3559116,
"label": "CONTAIN",
"to": 1774161,
"id": 9763079,
"type": 0
},
{
"from": 3559116,
"label": "MATCH",
"to": 3559072,
"id": 9763085,
"type": 1,
"proportion": 0,
"directionFlag": 0,
"noDirectionFlag": 0,
"complianceFlag": 1
},
{
"from": 3559116,
"label": "CONTAIN",
"to": 3334544,
"id": 9763082,
"type": 0
}
],
};
},
mounted() {
// 初始化
this.init();
},
methods: {
//初始化
init() {
let container = document.getElementById("network_id");
this.nodesArray.forEach(i => {
if (i.type == 'File') { // 文件
i.color = "#CAF982"
} else { // 项目
i.color = "#D9001B"
}
})
let data = { nodes: this.nodesArray, edges: this.edgesArray }
let options = {
autoResize: true, //网络将自动检测其容器的大小调整,并相应地重绘自身
locale: "cn", //语言设置:工具栏显示中文
// 设置节点样式
nodes: {
shape: "dot", //节点的外观。为circle时label显示在节点内,为dot时label显示在节点下方
size: 30, //节点的大小,
shadow: false, //如果为true,则节点使用默认设置投射阴影。
font: {
//字体配置
size: 20,
color: "rgb(117, 218, 167)",
align: "center",
},
color: {
border: "transparent", //节点边框颜色
background: "#ffc7c7", //节点背景颜色
highlight: {
//节点选中时状态颜色
border: "rgb(117, 218, 167)",
background: "rgb(117, 218, 167)",
},
hover: {
//节点鼠标滑过时状态颜色
border: "#dff9fb",
background: "#88dab1",
},
},
margin: 5, //当形状设置为box、circle、database、icon、text;label的边距
widthConstraint: 100, //设置数字,将节点的最小和最大宽度设为该值,当值设为很小的时候,label会换行,节点会保持一个最小值,里边的内容会换行
borderWidth: 1, //节点边框宽度,单位为px
borderWidthSelected: 3, //节点被选中时边框的宽度,单位为px
labelHighlightBold: false, //确定选择节点时标签是否变为粗体
},
// 边线配置
edges: {
width: 1,
length: 200,
color: {
color: "#848499",
highlight: "rgb(117, 218, 167)",
hover: "#88dab1",
inherit: "from",
opacity: 1.0,
},
smooth: {
//设置两个节点之前的连线的状态
enabled: true, //默认是true,设置为false之后,两个节点之前的连线始终为直线,不会出现贝塞尔曲线
},
arrows: { to: true }, //箭头指向to
},
interaction: {
hover: true,
hoverConnectedEdges: true
},
//计算节点之前斥力,进行自动排列的属性
physics: {
enabled: true, //默认是true,设置为false后,节点将不会自动改变,拖动谁谁动。不影响其他的节点
barnesHut: {
gravitationalConstant: -4000,
centralGravity: 0.3,
springLength: 120,
springConstant: 0.04,
damping: 0.09,
avoidOverlap: 0,
},
maxVelocity: 20,
minVelocity: 0.1
},
//用于所有用户与网络的交互。处理鼠标和触摸事件以及导航按钮和弹出窗口
// interaction: {
// hover: true,
// dragNodes: true, //是否能拖动节点
// dragView: true, //是否能拖动画布
// hover: true, //鼠标移过后加粗该节点和连接线
// multiselect: true, //按 ctrl 多选
// selectable: true, //是否可以点击选择
// selectConnectedEdges: true, //选择节点后是否显示连接线
// hoverConnectedEdges: true, //鼠标滑动节点后是否显示连接线
// zoomView: true, //是否能缩放画布
// },
//操作模块:包括 添加、删除、获取选中点、设置选中点、拖拽系列、点击等等
// manipulation: {
// enabled: true, //该属性表示可以编辑,出现编辑操作按钮
// addNode: true,
// addEdge: true,
// // editNode: undefined,
// editEdge: true,
// deleteNode: true,
// deleteEdge: true,
// },
};
let network = new Vis.Network(container, data, options);
// 鼠标点击事件
network.on("click", (e) => {
// 通过nodes:[],来判断是节点还是线
// 如果nodes是空则是线,反之则是节点
if (e.nodes.length != 0) {
// param.nodes 节点
} else {
// param.edges 线
}
})
//todo 悬停在节点上--显示弹框
network.on("hoverNode", (e) => {
let c = ''
data.nodes.forEach(i => {
if (i.id == e.node) {
c = i
}
})
let copyrights = '' // 版 权
if (c.copyrights.length != 0) {
c.copyrights.forEach(i => {
copyrights += i.context
})
}
var ul = ''
if (c.type == 'File') { // 文件
ul = "<ul>"
+ "<li>协 议:" + c.licenses.toString() + "</li>"
+ "<li>版 权:" + copyrights + "</li>"
+ "<li>" + (c.isStrongInfection == 1 ? '有' : '没有') + "著作权协议</li>"
+ "</ul>";
} else { // 项目
ul = "<ul>"
+ "<li>项目名称:" + c.label + "</li>"
+ "<li>版 本:" + c.version + "</li>"
+ "<li>发布时间:" + c.releaseTime + "</li>"
+ "<li>协 议:" + c.licenses.toString() + "</li>"
+ "<li>版 权:" + copyrights + "</li>"
+ "</ul>";
}
// js
let divHoverNode = document.getElementById("divHoverNode")
divHoverNode.innerHTML = ul
divHoverNode.style = `display:block;left: ${e.event.offsetX + 15}px;top: ${e.event.offsetY + 15}px`
// jQuery
// $("#divHoverNode").append(ul);
// $('#divHoverNode').css({
// 'display': 'block',
// 'left': e.event.offsetX + 15,
// 'top': e.event.offsetY + 15
// });
});
//todo 从节点移开---隐藏弹框
network.on('blurNode', () => {
// js
let divHoverNode = document.getElementById("divHoverNode")
divHoverNode.innerHTML = ''
divHoverNode.style = `display:none;`
// jQuery
// $("#divHoverNode").hide();
// $("#divHoverNode").empty();//移除之后清空div
});
// 拖拽节点
network.on("dragEnd", (e) => {
if (e.nodes && e.nodes.length > 0) {
// 拖拽节点后,使得节点可以固定不动
network.clustering.updateClusteredNode(e.nodes[0], {
physics: false,
});
}
});
},
},
};
</script>
<style lang="scss">
.Vis {
position: relative;
}
.menu {
/*这个样式不写,右键弹框会一直显示在画布的左下角*/
position: absolute;
background: rgba(3, 3, 3, 0.6);
border-radius: 5px;
left: -99999px;
top: -999999px;
color: #fff;
padding: 5px;
}
</style>