vue2使用d3.js实现网络拓扑图

vue2使用d3.js实现网络拓扑图

支持节点更换图标, 线条改变颜色

  • 安装
npm i d3@7.9.0 --save
  • 自定义组件
<template>
  <div style="width: 100%; height: 100%">
    <div ref="networkChart" class="network-chart"></div>

    <el-dialog title="详情" :visible.sync="dialog1" width="30%">
      详情
    </el-dialog>
  </div>
</template>

<script>
import * as d3 from 'd3'

export default {
  data() {
    return {
      nodes: [
        { id: 'node1', name: '192.168.1.11', image: require('@/assets/img/1.png') },
        { id: 'node2', name: '192.168.1.12', image: require('@/assets/img/2.png') },
        { id: 'node3', name: '192.168.1.13', image: require('@/assets/img/3.png') },
        { id: 'node4', name: '192.168.1.14', image: require('@/assets/img/4.png') },
      ],
      links: [
        { id: 'link1', source: 'node2', target: 'node1', distance: 100 },
        { id: 'link2', source: 'node3', target: 'node1', distance: 150 },
        { id: 'link3', source: 'node4', target: 'node1', distance: 200 },
      ],
      dialog1: false,
    }
  },
  mounted() {
    this.drawNetwork()

    setTimeout(() => {
      this.changeNodeLineStatus()
    }, 5000)
  },
  methods: {
    drawNetwork() {
      const width = this.$refs.networkChart.clientWidth
      const height = this.$refs.networkChart.clientHeight
      const imageSize = 40

      // 创建 SVG 画布
      const svg = d3.select(this.$refs.networkChart).append('svg').attr('width', width).attr('height', height)

      // 创建力导向图模拟
      const simulation = d3
        .forceSimulation(this.nodes)
        .force(
          'link',
          d3
            .forceLink(this.links)
            .id((d) => d.id)
            .distance((d) => d.distance) // 使用每条边的 distance 属性
        )
        .force('charge', d3.forceManyBody().strength(-100))
        .force('center', d3.forceCenter(width / 2, height / 2))

      // 绘制边
      const link = svg
        .append('g')
        .selectAll('line')
        .data(this.links)
        .enter()
        .append('line')
        .attr('id', (d) => d.id) // 设置边的 id
        .attr('stroke', '#008000') // 默认边颜色
        .attr('stroke-width', 2)

      // 绘制节点
      const node = svg
        .append('g')
        .selectAll('image')
        .data(this.nodes)
        .enter()
        .append('image')
        .attr('id', (d) => d.id) // 设置边的 id
        .attr('xlink:href', (d) => d.image) // 设置图片路径
        .attr('width', imageSize) // 图片宽度
        .attr('height', imageSize) // 图片高度
        .call(d3.drag().on('start', dragstarted).on('drag', dragged).on('end', dragended))
        .on('click', (event, d) => this.handleNodeClick(event, d)) // 节点点击事件

      // 添加节点标签
      const label = svg
        .append('g')
        .selectAll('text')
        .data(this.nodes)
        .enter()
        .append('text')
        .text((d) => d.name)
        .attr('fill', '#ffffff')
        .attr('dx', 20)
        .attr('dy', 4)

      // 更新节点和边的位置
      simulation.on('tick', () => {
        link
          .attr('x1', (d) => d.source.x)
          .attr('y1', (d) => d.source.y)
          .attr('x2', (d) => d.target.x)
          .attr('y2', (d) => d.target.y)

        node
          .attr('x', (d) => d.x - imageSize / 2) // 图片居中
          .attr('y', (d) => d.y - imageSize / 2)

        label.attr('x', (d) => d.x).attr('y', (d) => d.y)
      })

      // 拖拽事件
      function dragstarted(event) {
        if (!event.active) simulation.alphaTarget(0.3).restart()
        event.subject.fx = event.subject.x
        event.subject.fy = event.subject.y
      }

      function dragged(event) {
        event.subject.fx = event.x
        event.subject.fy = event.y
      }

      function dragended(event) {
        if (!event.active) simulation.alphaTarget(0)
        // event.subject.fx = null
        // event.subject.fy = null
        event.subject.fx = event.x
        event.subject.fy = event.y
      }
    },

    changeNodeLineStatus() {
      let index = 0
      setInterval(() => {
        if (index % 2 == 0) {
          d3.select('#link1').attr('stroke', '#ff000050')
        } else {
          d3.select('#link1').attr('stroke', '#ff0000')
        }
        index++
      }, 1000)

      d3.select('#node2').attr('xlink:href', require('@/assets/img/1red.png'))
    },

    // 节点点击事件处理
    handleNodeClick(event, clickedNode) {
      console.log('Clicked node:', clickedNode)

      this.dialog1 = true

      //   // 重置所有节点和边的颜色
      //   d3.selectAll('circle').attr('fill', '#69b3a2')
      //   d3.selectAll('line').attr('stroke', '#999')

      //   // 高亮点击的节点
      //   d3.select(event.currentTarget).attr('fill', 'orange')

      //   // 高亮与点击节点相连的边
      //   this.links.forEach((link) => {
      //     if (link.source.id === clickedNode.id || link.target.id === clickedNode.id) {
      //       d3.selectAll('line')
      //         .filter((d) => d.source.id === link.source.id && d.target.id === link.target.id)
      //         .attr('stroke', 'red')
      //     }
      //   })
    },
  },
}
</script>

<style lang="less" scoped>
.network-chart {
  width: 100%;
  height: 100%;
}
</style>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978133.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Uniapp-Vue3】导入uni-id用户体系

在uniapp官网的uniCloud中下载uni-id用户体系 或者直接进入加载&#xff0c;下载地址&#xff1a;uni-id-pages - DCloud 插件市场 进入以后下载插件&#xff0c;打开HbuilderX 选中项目&#xff0c;点击确定 点击跳过 点击合并 右键uniCloud文件夹下的database文件夹&#x…

如何免费使用稳定的deepseek

0、背景&#xff1a; 在AI辅助工作中&#xff0c;除了使用cursor做编程外&#xff0c;使用deepseek R1进行问题分析、数据分析、代码分析效果非常好。现在我经常会去拿行业信息、遇到的问题等去咨询R1&#xff0c;也给了自己不少启示。但是由于官网稳定性很差&#xff0c;很多…

VSCode+PlatformIO报错 找不到头文件

如图示&#xff0c;找不到目标头文件 demo工程运行正常&#xff0c;考虑在src文件夹内开辟自己的代码&#xff0c;添加后没有找到 找了些资料&#xff0c;大概记录如下&#xff1a; 1、c_cpp_properties.json 内记录 头文件配置 .vscode 中&#xff0c;此文件是自动生成的&a…

Python 网络爬虫实战全解析:案例驱动的技术探索

Python 网络爬虫实战全解析&#xff1a;案例驱动的技术探索 本文围绕 Python 网络爬虫展开&#xff0c;深入剖析其技术要点&#xff0c;并通过实际案例演示开发流程。从爬虫原理引入&#xff0c;逐步讲解如何使用 Python 中的requests和BeautifulSoup等库进行网页数据抓取与解…

List(3)

前言 上一节我们讲解了list主要接口的模拟实现&#xff0c;本节也是list的最后一节&#xff0c;我们会对list的模拟实现进行收尾&#xff0c;并且讲解list中的迭代器失效的情况&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 list的迭代器失效 之前在讲解vec…

在zotero里部署papaerschat插件,以接入现有大模型

papaerschat插件里集成了openAI的GPT3.5、gpt-4o、gpt-mini大模型以及Claude3、Gemini、Deepseek等大模型。通过接入这些大模型可以辅助我们阅读论文。以部署方式如下&#xff1a; 1.下载zotero的插件市场&#xff0c;用以管理zotero里的插件。下载地址&#xff1a; https://…

Memory Programming ...Error: File does not exist: Max.hex

Memory Programming ... Error: File does not exist: Max.hex 原因 删了确定就可以了

渗透测试【seacms V9】

搭建seacms环境 我选择在虚拟机中用宝塔搭建环境 将在官网选择的下载下来的文件解压后拖入宝塔面板的文件中 创建网站 添加站点 搭建完成seacmsV9 找到一个报错口 代码分析 <?php set_time_limit(0); error_reporting(0); $verMsg V6.x UTF8; $s_lang utf-8; $dfDbn…

仅需三分钟,使用Vue3.x版本组件式风格实现一个消息提示组件!

一、前言 在日常的前端项目开发中&#xff0c;我们时常需要使用到“消息提示”&#xff08;以下简称“消息”&#xff09;这个组件来帮助我们更好的给予用户提示&#xff0c;例如常见的“登录成功”、“操作成功”、“服务器异常”等等提示。 尽管市面上已经有一些组件库提供了…

敏捷开发实践指南:从理论到落地的全面解析

敏捷工程&#xff1a;现代软件开发的变革与实践 近年来&#xff0c;软件工程领域经历了从传统瀑布模型到敏捷开发的深刻转变。这种转变不仅是技术方法的升级&#xff0c;更是团队协作、需求管理和交付模式的革新。本文将从敏捷开发的核心理念、主流方法、实践案例及未来趋势等…

期权帮|股指期货基差和价差有什么区别?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 股指期货基差和价差有什么区别&#xff1f; 一、股指期货基差 股指期货基差是指股指期货价格与其对应的现货指数价格之间的差额。 股指期货基差计算公式&#xff1a;基差 现…

【论文解读】《C-Pack: Packed Resources For General Chinese Embeddings》

论文链接&#xff1a;https://arxiv.org/pdf/2309.07597 本论文旨在构建一套通用中文文本嵌入的完整资源包——C-Pack&#xff0c;解决当前中文文本嵌入研究中数据、模型、训练策略与评测基准缺失的问题。论文主要贡献体现在以下几个方面&#xff1a; 大规模训练数据&#xf…

ARM 处理器平台 eMMC Flash 存储磨损测试示例

By Toradex秦海 1). 简介 目前工业嵌入式 ARM 平台最常用的存储器件就是 eMMC Nand Flash 存储&#xff0c;而由于工业设备一般生命周期都比较长&#xff0c;eMMC 存储器件的磨损寿命对于整个设备来说至关重要&#xff0c;因此本文就基于 NXP i.MX8M Mini ARM 处理器平台演示…

html中的元素(2)

在用块级元素完成网页的组织和布局以后&#xff0c;要为其中的每一个小区块添加内容&#xff0c;就需要用到行内元素&#xff1a; 1.字体样式元素 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>HTML5 保留的文本格式元…

代码随想录二刷|动态规划12

dp动态规划 动态规划五步曲 动态规划数组的含义 dp[i] 递推公式 动态规划数组的初始化 确定遍历顺序 手动模拟验证 动态规划遇到问题要打印dp数组&#xff0c;看和模拟结果哪里不一样 一 基础问题 斐波那契数 题干 斐波那契数 &#xff08;通常用 F(n) 表示&#xf…

linux 系统 安装禅道教程

禅道&#xff08;ZenTao&#xff09;是一款开源的项目管理软件&#xff0c;特别适用于敏捷开发和团队协作。它集成了需求管理、任务管理、缺陷管理、版本管理、文档管理等功能&#xff0c;旨在帮助团队更高效地管理项目&#xff0c;提升工作协同和开发效率。 禅道的主要特点&a…

CineMaster: 用于电影文本到视频生成的 3D 感知且可控的框架。

CineMaster是一种 3D 感知且可控的文本到视频生成方法允许用户在 3D 空间中联合操纵物体和相机&#xff0c;以创作高质量的电影视频。 相关链接 论文&#xff1a;cinemaster-dev.github.io 论文介绍 CineMaster是一种用于 3D 感知和可控文本到视频生成的新型框架。目标是让用…

Linux红帽:RHCSA认证知识讲解(四)修改远程配置文件,取消root禁用,便于使用root身份远程

Linux红帽&#xff1a;RHCSA认证知识讲解&#xff08;四&#xff09;修改远程配置文件&#xff0c;取消root禁用&#xff0c;便于使用root身份远程 前言一、远程连接的用途和原因二、通过 ssh 远程登陆系统三、默认限制及解决方案&#xff08;一&#xff09;非常规方法一&#…

OpenEuler学习笔记(三十五):搭建代码托管服务器

以下是主流的代码托管软件分类及推荐&#xff0c;涵盖自托管和云端方案&#xff0c;您可根据团队规模、功能需求及资源情况选择&#xff1a; 一、自托管代码托管平台&#xff08;可私有部署&#xff09; 1. GitLab 简介: 功能全面的 DevOps 平台&#xff0c;支持代码托管、C…

Rk3568驱动开发_点亮led灯(手动挡)_5

1.MMU简介 完成虚拟空间到物理空间的映射 内存保护设立存储器的访问权限&#xff0c;设置虚拟存储空间的缓冲特性 stm32点灯可以直接操作寄存器&#xff0c;但是linux点灯不能直接访问寄存器&#xff0c;linux会使能mmu linux中操作的都是虚拟地址&#xff0c;要想访问物理地…