vis.js可视化的出发点之一是它们可以处理动态数据,并允许对数据进行操作。为了实现这一点,vis.js包括一个基于灵活键/值 DataSetDataView处理非结构化JSON数据的功能。

  • 数据集DataSet,存储JSON的ID对象。可增删改查,过滤排序…

  • 资料检视DataView,提供数据集上经过过滤或格式化的视图。通过订阅DataView中的更改,获取过滤或格式化的数据,而无需一直指定过滤器和字段类型

  • 数据管道DataPipe,DataPipe从一个DataSet 获取数据DataView,对其进行转换并传入第二个 DataSet,用于强制数据类型,更改结构…

一、总结

Vis.js 是一个动态的,基于浏览器的可视化库。该库被设计为易于使用,能处理大量的动态数据。该库由以下几部分组成:

一是数据集和数据视图,基于灵活的键/值数据集,可以添加,更新和删除项目,订阅数据集变化;

二是时间轴,用于显示不同类型的时间轴数据,在时间轴上项目可以交互移动,缩放和操纵;

三是图形,使用节点和边显示一个交互式图形或网络。

二、配置&使用

1.vis-network 入门

vue安装

# v4.21.0 不再维护
npm install vis# v9.0.1 建议使用下面这个
npm install vis-network

引入 vis-network

<template><div id="mynetwork" class="mynetwork"></div>
</template>
<script>
//v4.21.0
import * as vis from "vis";
export default {data() {return { network: null };},mounted() {this.init();},methods: {init() {// 节点var nodes = 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 edges = new vis.DataSet([{ id: 1, from: 1, to: 3 },{ id: 2, from: 1, to: 3 },{ id: 5, from: 3, to: 1 },{ from: 1, to: 2 },{ from: 2, to: 4 },{ from: 2, to: 5 },{ from: 3, to: 3 },]);// create a networkvar container = document.getElementById("mynetwork");var data = {nodes: nodes,edges: edges,};var options = {};this.network = new vis.Network(container, data, options);},},
};
</script><style scoped>
.mynetwork {height: 100%;
}
</style>

传统html页面使用

<html>
<head><script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script><style type="text/css">#mynetwork {width: 600px;height: 400px;border: 1px solid lightgray;}</style>
</head><body>
<div id="mynetwork"></div><script type="text/javascript">// 创建节点数据数组var nodes = 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 edges = new vis.DataSet([{ from: 1, to: 3 },{ from: 1, to: 2 },{ from: 2, to: 4 },{ from: 2, to: 5 },{ from: 3, to: 3 }]);// 获取容器var container = document.getElementById('mynetwork');// 将数据赋值给vis 数据格式化器var data = {nodes: nodes,edges: edges};var options = {};// 初始化关系图var network = new vis.Network(container, data, options);
</script>
</body>
</html>

效果如下

事件监听

交互模块触发

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, // pxstrokeWidth: 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.prdData(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, //已修改后的字段为imagehaschildren: haschildState,});if (clickNodeList.changEdge) {//初始中心节点无changEdgethis.edges.update({id: clickNodeList.changEdge,open: false,haschildren: haschildState,// length: 280,});}}});},prdData(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>

效果如下

功能点:

  1. 右键展开菜单,点击请求节点数据,或展开下级菜单

  2. 拖动节点或画布,菜单跟随节点

  3. 缩放画布,菜单同步缩放

  4. 对其它或者空白区域进行操作时,关闭菜单

自定义菜单
vis拓扑图 右键节点展开菜单

vis实现类知识图谱的拓扑图相关推荐

  1. 前沿技术探秘:知识图谱构建流程及方法

    作者 | 郑毅 封图| CSDN│下载于视觉中国 出品 | CSDN云计算(ID:CSDNcloud) 随着AI技术的发展和普及,当今社会已经进入了智能化时代.与以往不同的是,在这一波浪潮中,企业不仅 ...

  2. 人工智能的浪潮中,知识图谱何去何从?

    漆桂林认为,目前知识图谱整个领域最关注的问题还是如何能够高效.低成本构建知识图谱,而这个问题对于研究人员来说,仍是一个非常大的挑战,比如现在大家都在关注如何在少量甚至无标注场景下进行知识图谱构建. 记 ...

  3. 美团大脑:知识图谱的建模方法及其应用 | 公开课笔记

    参加 2018 AI开发者大会,请点击 ↑↑↑ 分享嘉宾 | 王仲远(美团 AI Lab NLP 中心负责人) 整    理 | 周翔 出    品 | AI科技大本营 作为人工智能时代最重要的知识表 ...

  4. 知识图谱的皇冠:知识图谱推理的前世今生

    作者:费斌杰 本文约4200字,建议阅读8分钟 本文聚焦于知识推理的理论研究和产业实践,剖析知识图谱推理的前世今生以及最近研究进展,以飨读者. [ 导读 ]业界和学界对知识图谱的关注主要集中于两大领域 ...

  5. 美团大脑:知识图谱的建模方法及其应用

    作为人工智能时代最重要的知识表示方式之一,知识图谱能够打破不同场景下的数据隔离,为搜索.推荐.问答.解释与决策等应用提供基础支撑.美团大脑围绕吃喝玩乐等多种场景,构建了生活娱乐领域超大规模的知识图谱, ...

  6. 应用实践 | 网络智能运维下的知识图谱

    本文转载自公众号:网络人工智能园地. 让AI更智能,谷歌要用知识图谱让AI像人一样理解世界. 让AI更智能,我们要用知识图谱让AI像网络专家一样了解网络. 知识图谱引领人工智能从感知阶段演进到认知阶段 ...

  7. 漆桂林 | 人工智能的浪潮中,知识图谱何去何从?

    本文转载自公众号:AI科技大本营. 近年来,随着人们对 AI 认知能力的积极探索,知识图谱因其表达能力强.拓展性好,基于知识进行推理等优势得到了学界与业界的高度关注.知识图谱,旨在描述客观世界概念.实 ...

  8. 美团大脑 | 知识图谱的建模方法及其应用

    本文转载自公众号: 美团技术团队. 作为人工智能时代最重要的知识表示方式之一,知识图谱能够打破不同场景下的数据隔离,为搜索.推荐.问答.解释与决策等应用提供基础支撑.美团大脑围绕吃喝玩乐等多种场景,构 ...

  9. 说实话:中文自然语言处理(知识图谱)的N个真实情况

    中文自然语言处理,目前在AI泡沫之下,真假难辨,实战技术与PPT技术往往存在着很大的差异.目前关于AI或者自然语言处理,做的人与讲的人往往是两回事. 1.深度学习在自然语言处理当中,除了在分类问题上能 ...

最新文章

  1. matplotlib 散点图和折线图画在一起_使用matplotlib.pyplot画折线图
  2. Android P 电量管理,Android P亮点汇总:更智能 更简单
  3. 拜托,面试别再问我表达式求值了!!!
  4. Subversion之路--实现精细的目录访问权限控制(v1.0 更新于2006.12.05)(二)
  5. mysql 打开远程服务
  6. 十大经典排序C++实现及动图演示
  7. xxx is not mapped 错误 解决方案
  8. oracle的dbcp工具类,DBCP数据源的使用
  9. vmware实现小型局域网实验环境
  10. Linux的工作队列work queue和延时工作队列
  11. Photoshop投影和CSS box-shadow转换
  12. 纯Css比较好看的中英文字体样式(持续整理版)
  13. 无刷直流电机控制MATLAB仿真,使用Simulink进行无刷直流电机控制仿真
  14. sourcetree拉取项目时报错,解决两个冲突
  15. python透视表画图_如何用Python实现透视表?
  16. Linux 系统结构详解
  17. html5 刮刮乐 源码,HTML5 canvas实现刮刮乐功能
  18. 从户外露营到登陆火星,火星玩家电核装备让太空黑科技成为现实
  19. ADI Blackfin DSP处理器-BF533的开发详解62:DSP控制ADXL345三轴加速度传感器-贪食蛇游戏(含源码)
  20. c语言深度剖析(12)—注释符号

热门文章

  1. 性能及稳定性测试方法
  2. 页面长时间未操作,实现自动退出登录原理
  3. 查寝 | c++ | 不用双向链表(下篇)
  4. 【问】默认实例名是多少?
  5. 最全《智慧园区解决方案》
  6. 如何计算ip地址及子网掩码
  7. 优秀的程序员!=爱写博客的程序员
  8. ioc基础(视图,资源,assert注入)-dhroid文档
  9. datagrid 设置表格高度
  10. 三个字摞一起念什么?【肯定有你不知道的】