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

news2025/2/27 23:01:08

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>


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录一下在k3s快速创建gitlab

废话不多说&#xff0c;直接上配置文件 需要修改的地方&#xff08;备注都有写&#xff09;&#xff1a; 1.命名空间 namespace 2. claimName 文件挂载 Deployment kind: Deployment apiVersion: apps/v1 metadata:name: gitlabnamespace: cicd # 替换为您的命名空间la…

AWQ和GPTQ量化的区别

一、前言 本地化部署deepseek时发现&#xff0c;如果是量化版的deepseek&#xff0c;会节约很多的内容&#xff0c;然后一般有两种量化技术&#xff0c;那么这两种量化技术有什么区别呢&#xff1f; 二、量化技术对比 在模型量化领域&#xff0c;AWQ 和 GPTQ 是两种不同的量…

线性模型 - 支持向量机

支持向量机&#xff08;SVM&#xff09;是一种用于分类&#xff08;和回归&#xff09;的监督学习算法&#xff0c;其主要目标是找到一个最佳决策超平面&#xff0c;将数据点分为不同的类别&#xff0c;并且使得分类边界与最近的数据点之间的间隔&#xff08;margin&#xff09…

湖北中医药大学谱度众合(武汉)生命科技有限公司研究生工作站揭牌

2025年2月11日&#xff0c;湖北中医药大学&谱度众合&#xff08;武汉&#xff09;生命科技有限公司研究生工作站揭牌仪式在武汉生物技术研究院一楼101会议室举行&#xff0c;湖北中医药大学研究生院院长刘娅教授、基础医学院院长孔明望教授、基础医学院赵敏教授、基础医学院…

面试基础---深入解析 AQS

深入解析 AQS&#xff1a;从源码到实践&#xff0c;剖析 ReentrantLock 和 Semaphore 的实现 引言 在 Java 并发编程中&#xff0c;AbstractQueuedSynchronizer&#xff08;AQS&#xff09;是一个核心框架&#xff0c;它为构建锁和其他同步器提供了基础支持。ReentrantLock 和…

从 0 到 1,用 Python 构建超实用 Web 实时聊天应用

从 0 到 1&#xff0c;用 Python 构建超实用 Web 实时聊天应用 本文深入剖析如何运用 Python 的 Flask 框架与 SocketIO 扩展&#xff0c;搭建一个功能完备的 Web 实时聊天应用。从环境搭建、前后端代码实现&#xff0c;到最终运行展示&#xff0c;逐步拆解关键步骤&#xff0…

Vue2+Element实现Excel文件上传下载预览【超详细图解】

目录 一、需求背景 二、落地实现 1.文件上传 图片示例 HTML代码 业务代码 2.文件下载 图片示例 方式一&#xff1a;代码 方式二&#xff1a;代码 3.文件预览 图片示例 方式一&#xff1a;代码 方式二&#xff1a;代码 一、需求背景 在一个愉快的年后&#xff…

[记录贴] 火绒奇怪的进程保护

最近一次更新火绒6.0到最新版&#xff0c;发现processhacker的结束进程功能无法杀掉火绒的进程&#xff0c;弹窗提示如下&#xff1a; 可能是打开进程时做了权限过滤&#xff0c;火绒注册了两个回调函数如下&#xff1a; 但奇怪的是&#xff0c;在另外一台机器上面更新到最新版…

【蓝桥杯】每天一题,理解逻辑(1/90)【Leetcode 移动零】

文章目录 题目解析讲解算法原理【双指针算法思路】(数组下标充当指针)如何划分和执行过程大致 代码详情 题目解析 题目链接&#xff1a;https://leetcode.cn/problems/move-zeroes/description/ 题目意思解析 把所有的零移动到数组的末尾保持非零元素的相对顺序 理解了这两层…

pycharm远程连接服务器运行pytorch

Linux部署pytorch 背景介绍 不同的开源代码可能需要不同的实验环境和版本&#xff0c;这时候的确体现出Anaconda管理环境的好处了&#xff0c;分别搞一个独立环境方便管理。 有的教程建议选择较旧的版本&#xff0c;但笔者建议在条件允许的情况下安装最新版&#xff0c;本次…

java练习(41)

ps&#xff1a;题目来自力扣 最接近的三数之和 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 import java.util.Arrays;class Solut…

PDF扫描档智能方向识别:多模型投票机制的实践测试 救活古典书籍

2025-02-22 20:10物联全栈123 尊敬的诸位&#xff01;我是一名物联网工程师。关注我&#xff0c;持续分享最新物联网与AI资讯和开发实战。期望与您携手探寻物联网与 AI 的无尽可能 RAG知识库搭建的过程中&#xff0c;扫描档pdf的支持和准确率一直是个大家都不愿主动提起的事情…

轻松搭建:使用Anaconda创建虚拟环境并在PyCharm中配置

一、使用Anaconda创建虚拟环境 1. 安装Anaconda 2..conda常用的命令 3. 创建虚拟环境-以搭建MachineVision为例 4. 激活虚拟环境 5. 安装依赖包 二、PyCharm配置环境 在进行Python项目开发时&#xff0c;合理的环境管理是必不可少的&#xff0c;特别是当你在多个项目中…

驱动开发系列39 - Linux Graphics 3D 绘制流程(二)- 设置渲染管线

一:概述 Intel 的 Iris 驱动是 Mesa 中的 Gallium 驱动,主要用于 Intel Gen8+ GPU(Broadwell 及更新架构)。它负责与 i915 内核 DRM 驱动交互,并通过 Vulkan(ANV)、OpenGL(Iris Gallium)、或 OpenCL(Clover)来提供 3D 加速。在 Iris 驱动中,GPU Pipeline 设置 涉及…

MinIO整合SpringBoot实现文件上传、下载

文章目录 配置1. 部署MinIO服务2. 整合SpringBoot 功能实现1. 文件上传2. 文件下载 总结 配置 1. 部署MinIO服务 这里以docker为例&#xff1a; 安装minio命令docker run -p 9000:9000 -p 9001:9001 \ --name minio \ -v /path/to/data:/data \ -e "MINIO_ROOT_USERmin…

FreeRTOS(3)列表List

在 FreeRTOS 的源码中大量地使用了列表和列表项&#xff0c;因此想要深入学习 FreeRTOS&#xff0c;列表和列表项是必备的基础知识。这里所说的列表和列表项&#xff0c;是 FreeRTOS 源码中 List 和 List Item 的 直译&#xff0c;事实上&#xff0c; FreeRTOS 中的列表和列表项…

C++和OpenGL实现3D游戏编程【连载23】——几何着色器和法线可视化

欢迎来到zhooyu的C++和OpenGL游戏专栏,专栏连载的所有精彩内容目录详见下边链接: 🔥C++和OpenGL实现3D游戏编程【总览】 1、本节实现的内容 上一节课,我们在Blend软件中导出经纬球模型时,遇到了经纬球法线导致我们在游戏中模型光照显示问题,我们在Blender软件中可以通过…

Harmony开发笔记(未完成)

一、感想 作为一名拥有11年经验的Android开发者&#xff0c;我亲历了Android从高速发展到如今面临“僧多粥少”的过程。技术的世界瞬息万变&#xff0c;没有一种技术能够让人依赖一辈子。去年初&#xff0c;我自学了鸿蒙系统&#xff0c;并顺利通过了鸿蒙官方的初级和高级认。…

【Java面试】创建线程有哪几种方式

目录 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口和FutureTask 4.使用Executor框架&#xff08;线程池&#xff09; Java并发编程中不同接口和类之间的关系 总结 1.继承Thread类 优点&#xff1a; 简单直观。直接继承Thread类&#xff0c;可以方便地使用Threa…

在Linux环境下利用MTCNN进行人脸检测(基于ncnn架构)

概述 本文将详细介绍如何在Linux环境下部署MTCNN模型进行人脸检测&#xff0c;并使用NCNN框架进行推理。 1. CMake的安装与配置 下载CMake源码 前往CMake官网下载&#xff0c;找到适合您系统的最新版本tar.gz文件链接&#xff0c;或者直接通过wget下载&#xff1a;CMake官方…