AntV-G6手动添加节点和边,实现拓扑图的可视化展示

文章展示了如何使用G6图形库来创建一个简单的交互式拓扑图。通过注册自定义事件,如click-add-node和click-add-edge,实现了单击添加节点和边的功能。用户还能修改节点和边的信息,并能获取当前拓扑图的数据。此外,提供了获取和修改节点及边数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一小时实现简单的手动添加节点和边,实现可视化展示

在这里插入图片描述
左边:取消添加节点和边、获取的拓扑图数据、添加节点、添加边
在这里插入图片描述

中间:可视化展示区域
在这里插入图片描述

右边:修改节点信息、修改边信息
在这里插入图片描述

下面是一些关键代码

根据官网修改G6设置交互模式

添加节点

注册自定义事件:G6.registerBehavior

    /**
     * @description 注册点击添加节点
     */
    addNode() {
      let _this = this;
      G6.registerBehavior("click-add-node", {
        // Set the events and the corresponding responsing function for this behavior
        getEvents() {
          // The event is canvas:click, the responsing function is onClick
          return {
            "canvas:click": "onClick",
          };
        },
        // Click event
        onClick(ev) {
          const self = this;
          const graph = self.graph;
          // Add a new node
          graph.addItem("node", {
            x: ev.canvasX,
            y: ev.canvasY,
            id: `node-${_this.addedCount}`, // Generate the unique id
            label: `node-${_this.addedCount}`,
          });
          _this.addedCount++;
        },
      });
    },

添加边

注册自定义事件:G6.registerBehavior

    /**
     * @description 注册点击添加边
     */
    addEdge() {
      G6.registerBehavior("click-add-edge", {
        // Set the events and the corresponding responsing function for this behavior
        getEvents() {
          return {
            "node:click": "onClick", // The event is canvas:click, the responsing function is onClick
            mousemove: "onMousemove", // The event is mousemove, the responsing function is onMousemove
            "edge:click": "onEdgeClick", // The event is edge:click, the responsing function is onEdgeClick
          };
        },
        // The responsing function for node:click defined in getEvents
        onClick(ev) {
          const self = this;
          const node = ev.item;
          const graph = self.graph;
          // The position where the mouse clicks
          // const point = { x: ev.x, y: ev.y };
          const model = node.getModel();
          if (self.addingEdge && self.edge) {
            graph.updateItem(self.edge, {
              target: model.id,
            });

            self.edge = null;
            self.addingEdge = false;
          } else {
            // Add anew edge, the end node is the current node user clicks
            self.edge = graph.addItem("edge", {
              source: model.id,
              target: model.id,
            });
            self.addingEdge = true;
          }
        },
        // The responsing function for mousemove defined in getEvents
        onMousemove(ev) {
          const self = this;
          // The current position the mouse clicks
          const point = { x: ev.x, y: ev.y };
          if (self.addingEdge && self.edge) {
            // Update the end node to the current node the mouse clicks
            self.graph.updateItem(self.edge, {
              target: point,
            });
          }
        },
        // The responsing function for edge:click defined in getEvents
        onEdgeClick(ev) {
          const self = this;
          const currentEdge = ev.item;
          if (self.addingEdge && self.edge === currentEdge) {
            self.graph.removeItem(self.edge);
            self.edge = null;
            self.addingEdge = false;
          }
        },
      });
    },

点击节点,获取当前节点数据并进行修改

// 注册事件
graph.on("node:click", this.onNodeClick);
// 获取数据
onNodeClick(e) {
  this.mode = "node";
  const item = e.item.getModel();
  this.nodeData.label = item.label;
  this.nodeData.id = item.id;
}
// 修改数据
changeNodeName() {
  if (this.nodeData.id) {
    const item = graph.findById(this.nodeData.id);
    graph.updateItem(item, {
      label: this.nodeData.label,
    });
  }
}

点击边,获取当前边数据并进行修改

// 注册事件
graph.on("edge:click", this.onEdgeClick);
// 获取数据
onEdgeClick(e) {
  this.mode = "edge";
  const item = e.item.getModel();
  this.edgeData.label = item.label;
  this.edgeData.id = item.id;
}
// 修改数据
changeEdgeName() {
  if (this.edgeData.id) {
    const item = graph.findById(this.edgeData.id);
    graph.updateItem(item, {
      label: this.edgeData.label,
    });
  }
}

获取当前拓扑图的数据

getData() {
  console.log(graph.save());
}

在这里插入图片描述
非常简单的demo,仓库地址
想要更多的自定义的节点和边,可以看该仓库下的另一个页面,或者G6官网

### Vue2 中实现拓扑图可视化的方法 尽管现代项目更倾向于使用 Vue3 或其他更新的技术栈,但在 Vue2 中仍然可以借助第三方库来实现拓扑图可视化。以下是几种常见的解决方案及其特点: #### 方法一:基于 ECharts 的实现 ECharts 是一个强大的图表库,支持多种复杂的图表类型,包括拓扑图(关系图)。虽然引用中提到的是 Vue3 ECharts 的组合[^1],但同样的逻辑也可以应用于 Vue2。 ##### 关键步骤: 1. **安装依赖** 需要先引入 ECharts 库以及其 Vue 组件 `vue-echarts`。 ```bash npm install echarts vue-echarts ``` 2. **配置组件** 创建一个 Vue 组件并初始化 ECharts 图表实例。 ```javascript import { ref, onMounted } from 'vue'; import * as echarts from 'echarts'; export default { setup() { const chartRef = ref(null); let myChart; onMounted(() => { myChart = echarts.init(chartRef.value); const option = { tooltip: {}, series: [ { type: 'graph', layout: 'force', // 使用力引导布局算法 data: [ { name: 'Node A' }, { name: 'Node B' }, { name: 'Node C' } ], links: [ { source: 'Node A', target: 'Node B' }, { source: 'Node B', target: 'Node C' } ] } ] }; myChart.setOption(option); }); return { chartRef }; } }; ``` 3. **模板部分** 在模板中定义用于渲染图表的 DOM 容器。 ```html <template> <div ref="chartRef" style="width: 600px; height: 400px;"></div> </template> ``` 这种方法的优点在于简单易用,适合初学者快速上手,并且可以通过调整 `option` 参数轻松定制拓扑图的表现形式。 --- #### 方法二:基于 AntV-G6实现 AntV-G6 是阿里巴巴推出的一款专注于图数据可视化的工具,提供了丰富的 API 支持复杂场景下的交互设计。如果需要更高程度的功能扩展或者更好的性能表现,则可以选择 G6 来替代 D3.js[^3]。 ##### 主要特性: - 提供开箱即用的数据绑定机制; - 自带迷你地图(Minimap)插件方便全局观察大范围结构; - 轻松处理大规模节点的关系网路; ##### 示例代码片段: ```javascript import G6 from '@antv/g6'; export default { mounted() { const graph = new G6.Graph({ container: 'mountNode', // 指定挂载容器ID width: window.innerWidth, height: window.innerHeight, modes: { default: ['drag-node'] // 默认模式允许拖拽顶点位置 } }); const data = { nodes: [{ id: 'nodeA', label: 'Node A' }, { id: 'nodeB', label: 'Node B' }], edges: [{ source: 'nodeA', target: 'nodeB' }] }; graph.data(data); // 加载数据源 graph.render(); // 渲染整个画布 } }; ``` 注意这里假设已经创建好 HTML 文件中的 `<div>` 元素作为绘图区域,例如: ```html <template> <div id="mountNode"></div> </template> ``` 相比传统方式来说,这种方式更加灵活高效,在面对大量动态变化的需求时尤为突出。 --- #### 方法三:自定义 Canvas/DOM 结合实现 对于某些特定场合下可能并不想完全依赖于现有的开源框架,而是希望通过手动控制每一个细节来自由发挥创意。此时就可以考虑利用原生 JavaScript 对 canvas 进行编程或者是操纵普通的 html dom 元素构建简单的连接线状结构表示关联性。 不过考虑到开发成本及时效等因素一般不推荐采用此类做法除非确实存在特殊限制条件无法满足现有方案的要求之外才做尝试。 --- ### 总结 综上所述,无论是选用成熟的第三方类库还是自己动手搭建基础模型都可以达成目标只是各有侧重而已。如果是追求便捷性功能性的话建议优先考察前两种途径——尤其是当涉及到较多高级特性的运用之时更是如此。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值