v-network-graph

v-network-graph 是一个专为Vue 3设计的交互式网络图形可视化组件。它基于SVG绘制,充分利用Vue的响应式系统和双向数据绑定特性,简化了动态数据驱动的复杂网络图的创建过程。该组件允许开发者实时操控图表,如添加或删除元素、改变节点位置及调整视觉样式等,无需复杂的集成工作,显著降低了学习成本和编码量。目前该库已经基本成熟,还有些小功能未完善,比如两个拓扑节点之间存在汇总边时,选中样式这个小功能还未完成开发,但是在实际开发中几乎不会对项目造成什么影响。

项目背景

网络系统中的各个层的网络设备资源,在运行过程中都可能发成故障,存在故障肯定就会有告警,故障引起的原因有很多,性能、网络、数据等等,为了方便用户直观的了解各个资源的动态信息,所以需要以资源关系绘制拓扑图大屏,以满足客户的需求,并且拓扑图需要支持可配置(节点,边,文本,背景)。

将v-network-graph集成到项目

注意:官网上的例子是以ts编写的,我这里由于项目原因以js编写。

1.下载

npm/pnpm install v-network-graph

2. 在项目入口文件main.js

// main.js
import { createApp } from "vue"
import VNetworkGraph from "v-network-graph"
import "v-network-graph/lib/style.css"
import App from "./App.vue"

const app = createApp(App)

app.use(VNetworkGraph)
app.mount("#app")

# 也可以在组件中局部引入,无需全局注册

<!-- YourVueComponent.vue -->
<script setup lang="ts">
  import { VNetworkGraph } from "v-network-graph"
  import "v-network-graph/lib/style.css"
  ...
</script>

3.创建自己的画布组件

<template>
<v-network-graph class="networkContainer">

</v-network-graph>
</template>
<script setup>
  
</script>
<style lang="scss">
.networkContainer {
    ...yourself style
}
</style>

4.创建网络图需要的必要参数。

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="edges"
  />
</template>
<script setup>

// nodes 该参数代表网络图的所有节点的数据

 const nodes = {
    node1: { name: "Node 1" },
    node2: { name: "Node 2" },
    node3: { name: "Node 3" },
    node4: { name: "Node 4" },
 }

// edges 该参数代表网络图的所有节点之间的边数据

const edges = {
    edge1: { source: "node1", target: "node2" },
    edge2: { source: "node2", target: "node3" },
    edge3: { source: "node3", target: "node4" },
}
</script>

完成以上四部就可以绘制出一个简单的网络图了。

如何让拓扑图变得复杂一些呢

如上简单的拓扑图肯定满足不了复杂的项目需求,我下面会从三个方面深入:

布局

如果你要自定义布局,那么会有layouts属性进行布局,x,y的值代表节点在画布上的坐标值。

const layouts = {
  nodes: {
    node1: { x: 0, y: 0 },
    node2: { x: 50, y: 50 },
    node3: { x: 100, y: 0 },
    node4: { x: 150, y: 50 },
  },
}

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="edges"
    :layouts="layouts"
  />
</template>

可配置节点和边

如果要对边和节点的自定义配置,必须添加configs属性。

const config = {
    node: {
      normal: {
        type: "circle",
        radius: node => node.size, // Use the value of each node object
        color: node => node.color,
      },
      hover: {
        radius: node => node.size + 2,
        color: node => node.color,
      },
      selectable: true,
      label: {
        visible: node => !!node.label,
      },
      focusring: {
        color: "darkgray",
      },
    },
    edge: {
      normal: {
        width: edge => edge.width, // Use the value of each edge object
        color: edge => edge.color,
        dasharray: edge => (edge.dashed ? "4" : "0"),
      },
    },
}

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="edges"
    :layouts="layouts"
    :configs="configs"
  />
</template>

注意:如果你不需要动态去改变边或者节点的某个属性,属性值不需要写成箭头函数的方式,可以直接写成具体的常量。

其实除了边和节点的配置以外,还有很多很多,并且还能对画布view进行属性配置等等,我就在这里不一一赘述了,如果有兴趣可以详细阅读下面的文档;(此文档问英文文档,需要的可借助翻译软件更容易理解)

v-network-graph官方文档icon-default.png?t=O83Ahttps://dash14.github.io/v-network-graph/examples/appearance.html

复杂场景来了

元素层级问题

官方文档上对于层级问题是这么描述的,大概意思就是,需要自定义层级问题的话需要在配置文件的视图view属性上去设置。

You can add layers in the SVG generated by v-network-graph.

To add a layer, define the layer name and insertion position in the attribute, and define a named slot with the specified layer name in.

 下图是图层各类型元素默认的层顺序:

自定义层级

在configs配置属性的view属性上添加如下配置信息,可以根据自己的业务场景调整其顺序;

const topoConfig = {
  view: {
    builtInLayerOrder: ['edge-labels', 'edges', 'node-labels', 'nodes'],
  },
  ...其他配置属性
}

 重点:图层元素对应的数组索引越小层级越高,如果不写某些图层元素则会拿默认值元素索引定义层级。

自定义元素内容

元素自定义是很常见的业务场景,官方针对节点,节点标题(label),边都提供了对应的插槽入口

      # 替换节点插槽
      <template #override-node="{ nodeId, scale, config }">
      </template>

      # 替换label插槽
      <template #override-node-label="{ scale, text }">
      </template>

      # 替换边的插槽
      <template #edge-overlay="{ edge, scale, length, pointAtLength }">
      </template>

      # 自定义边的标记形状
       <defs>
          <marker
            id="marker-custom-diamond"
            markerWidth="6"
            markerHeight="6"
            refX="3"
            refY="3"
            orient="auto"
            markerUnits="strokeWidth"
          >
            <polygon points="0 3, 3 0, 6 3, 3 6" fill="#ff6666" />
         </marker>
       </defs>

 如上的代码怕片段插槽能提供的参数只写了部分,其它参数可以去官方文档案例中查看;由于该库是基于svg编写的,所以自定义内容需要利用svg的标签编写,具体的svg标签用途和功能可以阅读该文档;https://developer.mozilla.org/zh-CN/docs/Web/SVGicon-default.png?t=O83Ahttps://developer.mozilla.org/zh-CN/docs/Web/SVG

 图形元素的事件对象

绘制出复杂的网路图后,用户交互场景也同样重要,组件提供了event-handlers这个参数来实现交互场景。事件对象包含两大类,组件事件对象和图层事件对象。

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="edges"
    :layouts="layouts"
    :configs="configs"
    :event-handlers="eventHandlers"
  />
</template>
<script setup>
const eventHandlers = {
 // 视图鼠标左击操作
  "view:click": ({ event}) => {
    // 自定义交互内容
  },
   // 视图鼠标左键双击操作
  "view:dblclick": ({ event }) => {
    // 自定义交互内容
  },
  ...

   // 节点鼠标左击操作
  "node:click": ({ node }) => {
    // toggle
    nodes[node].active = !nodes[node].active
  },
   // 节点鼠标左键双击操作
  "node:dblclick": ({ node, event }) => {
    // toggle
    nodes[node].active = !nodes[node].active
  },
  ...

 // 鼠标左击边操作
  "edge:click": ({ edge, deges, event, summarized}) => {
    // 自定义交互内容
  },
   // 鼠标左键双击边操作
  "edge:dblclick": ({ deges, event, summarized }) => {
    // 自定义交互内容
  },
  ...
}
</script>

上面只罗列了视图,节点,边的单击和双击事件对象,还有很多可以在文档上查找。除了元素交互方法外,还给开发者暴露了一些方法:

 这些方法如何调用呢?


<template>
  <v-network-graph
    ref="graphRef"
    v-model:selected-nodes="selectedNodes"
    v-model:selected-edges="selectedEdges"
    :nodes="nodes"
    :edges="edges"
    :layouts="data.layouts"
    :configs="data.configs"
  />
</template>
<script setup>
import { ref } from 'vue'

const graphRef = ref(null) // 网络图ref

// 调用方法
async function downloadAsSvg() {
  if (!graph.value) return
  const text = await graphRef.value.exportAsSvgText()
  const url = URL.createObjectURL(new Blob([text], { type: "octet/stream" }))
  const a = document.createElement("a")
  a.href = url
  a.download = "network-graph.svg" // filename to download
  a.click()
  window.URL.revokeObjectURL(url)
}

</script>

 总结

v-network-graph这个库提供很多功能,能满足很多复杂的业务场景,上面是我在开发中自己总结学习的东西,整理了最常用的功能点,还有很多功能就不一一赘述,需要深入了解的小伙伴一定要仔细阅读我上面提供的文档,希望我的内容能帮到遇到同样问题的小伙伴!欢迎评论留言。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐