当前位置: 首页 > news >正文

用 Vue 3 + D3.js 实现动态数据流图

文章目录

  • 一、项目背景与功能概览
  • 二、项目准备与依赖安装
    • 2.1 安装 Vue 3 项目
    • 2.2 安装 D3.js
    • 2.3 项目结构
  • 三、实现动态数据流图
    • 3.1 创建 DataFlowChart 组件
    • 3.2 动态更新数据流
      • 3.2.1 动态更新边和节点位置
      • 3.2.2 动画效果
  • 四、节点拖拽与编辑功能实现
    • 4.1 添加节点拖拽功能
    • 4.2 编辑节点功能

一、项目背景与功能概览

数据流图是一种重要的可视化图形,广泛应用于表示系统或流程的输入输出。通过数据流图,我们能够更清晰地展示数据的流动和交互过程。本项目将使用 Vue 3D3.js 来创建一个动态的数据流图,支持节点与边的动画效果,并实时更新数据流动。

核心功能包括:

  • 动态数据流展示
  • 节点与边的交互动画
  • 实时数据更新与流动可视化

二、项目准备与依赖安装

2.1 安装 Vue 3 项目

首先,使用 Vue CLI 创建一个 Vue 3 项目,并选择 TypeScript 模板:

npm create vite@latest vue-d3-flow-chart --template vue-ts
cd vue-d3-flow-chart
npm install

2.2 安装 D3.js

我们需要使用 D3.js 来实现数据流图的可视化。安装 D3.js:

npm install d3

2.3 项目结构

项目结构如下:

src/
 ├── assets/
 ├── components/
 │    └── DataFlowChart.vue
 ├── views/
 │    └── Home.vue
 ├── App.vue
 └── main.ts

三、实现动态数据流图

3.1 创建 DataFlowChart 组件

src/components 目录下创建 DataFlowChart.vue,这是数据流图的核心组件。我们将使用 D3.js 来绘制节点和边,并利用 Vue 3 的组合式 API 来管理图的状态。

<template>
  <div ref="chart" class="data-flow-chart"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import * as d3 from 'd3'

// 数据流图的节点与边
const nodes = [
  { id: 1, name: '数据源' },
  { id: 2, name: '处理模块' },
  { id: 3, name: '存储模块' },
]

const links = [
  { source: 1, target: 2 },
  { source: 2, target: 3 },
]

// 组件挂载后的数据流图渲染
const chartRef = ref(null)

onMounted(() => {
  const width = chartRef.value.clientWidth
  const height = chartRef.value.clientHeight

  // 创建 D3 图形容器
  const svg = d3.select(chartRef.value)
    .append('svg')
    .attr('width', width)
    .attr('height', height)

  // 绘制节点
  const nodeElements = svg.selectAll('.node')
    .data(nodes)
    .enter().append('circle')
    .attr('class', 'node')
    .attr('r', 20)
    .attr('cx', (d, i) => 100 + i * 150)
    .attr('cy', height / 2)
    .style('fill', '#69b3a2')

  // 绘制节点标签
  svg.selectAll('.node-text')
    .data(nodes)
    .enter().append('text')
    .attr('class', 'node-text')
    .attr('x', (d, i) => 100 + i * 150)
    .attr('y', height / 2 - 30)
    .style('text-anchor', 'middle')
    .text(d => d.name)

  // 绘制边
  svg.selectAll('.link')
    .data(links)
    .enter().append('line')
    .attr('class', 'link')
    .attr('x1', d => 100 + (d.source - 1) * 150)
    .attr('y1', height / 2)
    .attr('x2', d => 100 + (d.target - 1) * 150)
    .attr('y2', height / 2)
    .style('stroke', '#999')
    .style('stroke-width', 2)
})
</script>

<style scoped>
.data-flow-chart {
  width: 100%;
  height: 400px;
}
.node {
  fill: #69b3a2;
  cursor: pointer;
  transition: fill 0.3s ease;
}
.node:hover {
  fill: #ff5722;
}
.link {
  stroke: #999;
  stroke-width: 2;
}
.node-text {
  font-size: 12px;
  fill: #333;
}
</style>

3.2 动态更新数据流

我们可以通过 D3.js 的更新机制,动态更新节点和边。例如,可以在节点之间传递数据或触发动画。

3.2.1 动态更新边和节点位置

// 监听数据变化并更新图形
const updateChart = (newLinks, newNodes) => {
  // 更新边
  const link = svg.selectAll('.link')
    .data(newLinks)
  link.enter().append('line')
    .merge(link)
    .attr('x1', d => 100 + (d.source - 1) * 150)
    .attr('y1', height / 2)
    .attr('x2', d => 100 + (d.target - 1) * 150)
    .attr('y2', height / 2)

  // 更新节点
  const node = svg.selectAll('.node')
    .data(newNodes)
  node.enter().append('circle')
    .merge(node)
    .attr('cx', (d, i) => 100 + i * 150)
    .attr('cy', height / 2)
}

3.2.2 动画效果

我们可以为节点和边添加动画效果,增强交互性。例如,在节点之间传递数据时,模拟数据流动的过程。

// 节点动画
node.transition()
  .duration(500)
  .attr('r', 30)
  .style('fill', '#ff5722')
  .transition()
  .duration(500)
  .attr('r', 20)
  .style('fill', '#69b3a2')

四、节点拖拽与编辑功能实现

4.1 添加节点拖拽功能

通过 D3.js 提供的拖拽功能,允许用户拖动节点,改变节点的位置。以下是拖拽实现代码:

// 节点拖拽
node.call(d3.drag()
  .on('start', dragStarted)
  .on('drag', dragged)
  .on('end', dragEnded)
)

function dragStarted(event) {
  d3.select(this).raise().attr('stroke', 'black')
}

function dragged(event) {
  d3.select(this)
    .attr('cx', event.x)
    .attr('cy', event.y)
}

function dragEnded() {
  d3.select(this).attr('stroke', null)
}

4.2 编辑节点功能

用户可以点击节点编辑其内容,如名称或颜色。实现代码如下:

// 节点点击编辑
node.on('click', (event, d) => {
  const newName = prompt('输入新的节点名称', d.name)
  if (newName) {
    d.name = newName
    d3.select(this).select('text').text(newName)
  }
})

—> 到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕

在这里插入图片描述

相关文章:

  • noscript 标签是干什么的
  • Linux上位机开发实践(关于Qt的移植)
  • 具身智能零碎知识点(三):深入解析 “1D UNet”:结构、原理与实战
  • Python_levl2.3函数
  • 【AutoTest】自动化测试工具大全(Python)
  • 限流、降级、熔断、隔离?
  • 【Hyperlane 】轻松实现大文件分块上传!
  • 六、测试分类
  • Python中NumPy的逻辑和比较
  • API 请求失败时的处理方法
  • 如何使用MaxScript+dotNet在UI中显示图像?
  • 大模型LLM表格报表分析:markitdown文件转markdown,大模型markdown统计分析
  • SpringBoot分布式项目中实现智能邮件提醒系统
  • 深度学习学习笔记
  • 【c语言】猜凶手
  • (十九)安卓开发中的Application类的使用详解
  • LLaMA-Factory双卡4090微调DeepSeek-R1-Distill-Qwen-14B医学领域
  • Python itertools模块的groupby函数介绍
  • ctfshow WEB web12
  • 【力扣05】最长回文子串
  • 360免费wifi连不上/青岛网站建设方案优化
  • 成都新都网站开发/网上商城推广13种方法
  • 一个网站怎么推广/好消息tvapp电视版
  • 天元建设集团有限公司邮编/seo排名优化价格
  • cms电影网站模板/个人如何做seo推广
  • 类似于拼多多的网站怎么做/seo软文代写