用 Vue.js 与 D3 打造可交互的社交网络可视化:Data-Science-For-Beginners 课程 Dangerous Liaisons 项目从搭建到运行
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
导读
本文面向想要快速上手「数据可视化」实战的开发者,完整讲解 Data-Science-For-Beginners 课程第 13 课「有意义的可视化(Making Meaningful Visualizations)」配套的 Dangerous Liaisons 项目:这是一个基于 Vue.js 3 与 D3 网络可视化库(vue-d3-network)的单页应用,用于将法国书信体小说《危险关系(Les Liaisons Dangereuses)》中的 1261 行信件数据渲染为一幅可拖拽、可交互的社交网络图。读完本文,你将掌握该 Vue CLI 工程从环境准备、依赖安装、开发运行、生产构建到补全核心连线逻辑(createLinks)的完整流程,并理解每个 npm 脚本与关键源码文件的职责。
项目背景:为什么用一封信件的网络图做练习
《危险关系》是法国作家肖代洛·德·拉克洛(Choderlos de Laclos)于 1782 年出版的书信体小说,故事以瓦勒蒙子爵(Vicomte de Valmont)与梅尔特伊侯爵夫人(Marquise de Merteuil)两位主角的通信为线索展开。小说全文由人物之间往来的信件组成,天然带有「发信人(from)」与「收信人(to)」的结构化关系——这正是构建社交网络图(Social Network Graph)的理想数据来源。
课程的第 13 课正是围绕「如何做出有意义的可视化」展开:选择正确的图表类型、避免误导性图表、正确处理颜色、提升可读性,以及如何构建动效与 3D 可视化。而 Dangerous Liaisons 项目就是该课的收尾实战:把信件数据映射为节点(人物)与连线(信件往来),在浏览器中以动画方式呈现这出 18 世纪法国贵族社会的关系图谱。项目运行后,你可以用鼠标拖动节点,实时观察「谁在给谁写信」的社交结构,直观地定位故事中的核心人物。
本次要讲解的 starter 工程 是一个已经搭好框架、留有一处待补全逻辑(createLinks()方法)的 Vue CLI 项目;仓库内还提供了 solution 完整版 供对照参考。
环境准备:Node.js 与 npm 版本要求
在安装依赖之前,请先确认本机已具备 Node.js 与 npm 环境。项目对 Node 版本有明确要求:Node >= 20.0.0。这一约束同时出现在工程根目录的 starter/README.md 与 package.json 的engines字段中:
"engines": { "node": ">=20.0.0" }engines字段是 npm 生态中声明运行时兼容性的标准方式,配合.npmrc(如engine-strict=true)可强制在安装时校验版本。如果本机 Node 版本低于 20,建议先通过 nvm 等工具升级,否则npm install可能抛出 engine 警告,某些依赖(尤其是较新版本的构建工具链)也可能无法正常工作。可以在终端用node -v与npm -v快速确认当前版本。
项目安装:npm install
进入3-Data-Visualization/13-meaningful-visualizations/starter目录后,运行:
npm install该命令会依据 package.json 拉取全部依赖。从依赖清单可以了解这个工程的技术栈构成:
"dependencies": { "core-js": "^3.6.5", "vue": "^3.5.16", "vue-d3-network": "0.1.28" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-plugin-eslint": "~5.0.8", "@vue/cli-service": "~5.0.8", "babel-eslint": "^10.1.0", "eslint": "^9.34.0", "eslint-plugin-vue": "^10.4.0", "vue-template-compiler": "^2.6.11" }- vue ^3.5.16:应用主体框架,本工程采用 Composition 风格较早期的 Options API 写法(详见下文源码解析);
- vue-d3-network 0.1.28:核心可视化库,它基于 Vue.js 与 D3 封装,将节点(nodes)与连线(links)数据渲染为可拖拽的力导向网络图;
- @vue/cli-service ~5.0.8:Vue CLI 构建服务,
serve、build、lint三个脚本都经由它执行; - core-js:为低版本浏览器提供 ES 新特性的 polyfill(与 Babel 配置配合工作)。
值得留意的是,package.json末尾还有一段overrides配置,将若干传递依赖锁定到较新的安全版本:
"overrides": { "qs": "6.14.2", "braces": ">=3.0.3", "webpack-dev-server": { "ws": "8.21.0" }, "webpack-bundle-analyzer": { "ws": "7.5.11" }, "serialize-javascript": "7.0.5" }从配置内容可以推断,这是为了修复 Webpack 工具链中传递依赖的已知安全问题而统一锁定的版本——这也是工程维护者保证可复现、可安全构建的一种常见做法。
开发模式运行:npm run serve
安装完成后,启动本地开发服务器:
npm run serve该脚本执行vue-cli-service serve,其作用包括:
- 编译与热重载(hot-reload):修改
src/下的.vue、.js文件后,页面会自动刷新或局部更新,无需手动重启,非常适合边改边调试可视化效果; - 启动本地开发服务器:本仓库未提供
vue.config.js自定义配置,因此端口、代理等均采用 Vue CLI 默认行为(默认监听 8080 端口),终端会打印可访问的本地地址; - 编译错误与警告提示:若代码存在语法错误,终端会即时反馈,便于快速定位问题。
启动成功后,浏览器打开终端提示的地址,即可看到 Dangerous Liaisons 信件网络图。注意:此刻连线还是空的,因为 Nodes.vue 中的createLinks()尚未补全——这是本项目的核心作业,下文会详细讲解。
生产构建:npm run build
当可视化逻辑完成后,可以为部署生成优化产物:
npm run build该脚本执行vue-cli-service build,会完成以下工作:
- 编译并压缩(minify):将所有
.vue单文件组件、JavaScript 与样式打包为压缩后的静态资源; - 按 browserslist 目标优化:
package.json中的browserslist字段声明了兼容目标:
"browserslist": [ "> 1%", "last 2 versions", "not dead" ]即「全球使用率超过 1% 的浏览器、各主流浏览器的最近两个大版本、仍处于维护期的浏览器」——Babel 与 Autoprefixer 会据此决定哪些语法需要转译、哪些 CSS 属性需要加前缀,从而在兼容性与产物体积之间取得平衡;
- 产物输出到
dist/目录:dist/是纯静态文件,可直接托管到任意静态 Web 服务器(这正是 assignment.md 中建议的「尝试将其部署为静态 Web 应用」的依据)。
代码检查与修复:npm run lint
项目内置了 ESLint 代码规范检查:
npm run lint该脚本执行vue-cli-service lint,依据package.json中的eslintConfig配置进行校验并自动修复可修复的问题:
"eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "eslint:recommended" ], "parserOptions": { "parser": "babel-eslint" }, "rules": {} }plugin:vue/essential:Vue 官方推荐的必备规则集,能拦截模板中的明显错误写法;eslint:recommended:ESLint 内置的推荐规则;parser: babel-eslint:让 ESLint 能解析 Vue 单文件组件中的现代 JavaScript 语法。
项目结构:从入口到核心组件的源码解析
为了理解「在哪里补全代码」,先梳理starter/的目录结构:
starter/ ├── public/ │ ├── favicon.ico # 站点图标 │ └── index.html # HTML 入口模板 ├── src/ │ ├── assets/ │ │ └── letters.json # 小说全部信件数据(1261 行,含 from / to / date / location) │ ├── components/ │ │ └── Nodes.vue # 网络可视化核心组件(待补全 createLinks) │ ├── App.vue # 根组件,挂载 Nodes │ └── main.js # Vue 应用入口 ├── README.md # 项目说明与命令清单 ├── babel.config.js # Babel 转译配置 └── package.json # 依赖与脚本定义启动链路非常清晰。入口 main.js 创建 Vue 实例并挂载到#app:
import Vue from "vue"; import App from "./App.vue"; Vue.config.productionTip = false; new Vue({ render: h => h(App) }).$mount("#app");根组件 App.vue 只做一件事——渲染Nodes组件:
<template> <div id="app"> <Nodes /> </div> </template> <script> import Nodes from "./components/Nodes"; export default { name: "App", components: { Nodes, }, }; </script>真正的核心是 Nodes.vue。模板部分直接使用vue-d3-network提供的<d3-network>组件,把节点、连线和选项绑定进去:
<template> <div class="hello"> <d3-network :net-nodes="nodes" :net-links="links" :options="options" /> </div> </template>组件脚本的关键逻辑如下(逐段解读):
- 引入库与数据:
import D3Network from "vue-d3-network"引入网络图组件;import letters from "../assets/letters.json"引入信件数据; - data 状态:
nodes与links分别承载网络节点与连线;nodeSize控制节点尺寸;canvas控制渲染方式(false 表示使用 SVG 而非 Canvas); - computed 的 options:向
vue-d3-network传递力导向布局与显示选项(详见下节); - created 生命周期:声明了小说中的 15 个人物名单(
characters数组,包含"Vicomte de Valmont"、"Marquise de Merteuil"、"Cécile Volanges"等),随后调用this.createLinks(characters)生成连线,并遍历人物为每个节点设置id、name、_size与随机颜色_color。
其中getCount(name)方法统计某个人物收到的信件数,用于决定节点大小:
getCount(name) { var count = 0; for (var i = 0; i < letters.length; i++) { if (letters[i].to === name) { count++; } } return count; }核心作业:补全 createLinks() 让连线出现
启动项目后网络图「只有节点没有连线」的原因,就在于 starter 版 Nodes.vue 中的createLinks()是空实现:
methods: { createLinks(characters) { //complete this code }, ... }数据源 letters.json 的结构非常简单,每条记录包含letter_num、from、to、date、location等字段:
{ "letter_num": 1, "from": "Cécile de Volanges", "to": "Sophie Carnay", "date": "8/3/17**", "location": "Ursulines" }而vue-d3-network期望的连线对象是{ sid: <源节点id>, tid: <目标节点id> }形式。因此任务可以拆解为两步:把每个人物映射为其在characters数组中的下标,再遍历每封信,构造{ sid, tid }对象 push 进links。课程给出的嵌套循环解法如下:
createLinks(characters) { //loop through letters let f = 0; let t = 0; for (var i = 0; i < letters.length; i++) { for (var j = 0; j < characters.length; j++) { if (characters[j] == letters[i].from) { f = j; } if (characters[j] == letters[i].to) { t = j; } } this.links.push({ sid: f, tid: t }); } }该实现与 solution 完整版 中的写法完全一致。补全后重新保存文件,热重载会自动生效,画布上便会绘制出人物之间的信件往来连线;你还可以拖动节点,观察力导向布局如何重新排布整个网络。
进阶思考(可自行尝试的优化方向):上述循环对每封信都执行了一次 O(n×m) 的双层遍历;若人物数量或信件规模增大,可将人物名到下标的映射提前构建为Map以降低复杂度。此外,f、t未命中人物名单时会残留上一次循环的值,可考虑在匹配不到时跳过该信件或给出默认值——这些都属于在理解作业基础上的合理深化,不作为本课程的必做要求。
可视化选项解析:force、size 与标签
Nodes.vue的 computedoptions对象直接控制网络图的物理仿真与显示效果:
computed: { options() { return { force: 3000, // 力导向布局的斥力强度,数值越大节点越分散 size: { w: 600, h: 600 }, // 画布宽高(像素) offset: { x: 0, y: 0 }, // 画布偏移量 nodeLabels: true, // 是否显示节点上的姓名标签 linkLabels: true, // 是否显示连线上的标签 canvas: this.canvas, // false:使用 SVG 渲染;true:切换为 Canvas 渲染 }; }, },- force:力导向图(force-directed graph)的核心参数,控制节点间的排斥力,数值越大,节点之间的间距越大、布局越松散;
- nodeLabels / linkLabels:开启后节点旁会标注人物姓名、连线上会标注对应内容,极大提升可读性——这正是第 13 课「为可读性而设计(Styling your charts for readability)」的实践体现;
- canvas:
false时走 SVG 渲染(便于样式定制与 DOM 调试),true时切换为 Canvas(适合海量节点的高性能场景)。本组件在data()中声明了canvas: false,因此默认采用 SVG。
配合 Nodes.vue 内置的样式表(如节点悬停高亮stroke-width: 5px、选中态描边#caa455、连线半透明绿色等),整个网络图已经具备较好的交互反馈与视觉层次。
自定义配置与后续扩展
starter/README.md 最后提到「Customize configuration」。由于本工程未提供vue.config.js文件,所有 Vue CLI 行为均使用默认值;若需调整端口、公共路径、代理等,可在工程根目录新建vue.config.js并按 Vue CLI 官方配置参考修改——注意这是对工程的自定义扩展,不是本仓库既有的内容。
完成可视化补全后,课程给出了进一步的挑战练习(见 assignment.md):
参考本项目中的社交网络示例,为「你自己的社交互动」构造数据——可以是你的社交媒体使用记录,也可以是家庭成员关系图,打造一个展示独特社交网络可视化的 Web 应用。
评分标准强调:代码能正常运行(可尝试部署为静态 Web 应用)、提供带注释说明的 README。因此一个完整交付物应当包含:可运行的工程、清晰的文档,以及通过npm run build产物部署到静态托管的能力。此外,第 13 课正文(3-Data-Visualization/13-meaningful-visualizations/README.md)还给出了更具挑战性的方向:自己上网搜集「误导性图表」并尝试修正,以此巩固「有意义可视化」的判读能力。
小结
Dangerous Liaisons 项目虽然只是一个 Vue CLI 脚手架工程,却完整覆盖了「数据 → 结构 → 可视化」的典型链路:letters.json是结构化的信件数据,createLinks()完成从原始数据到图结构(nodes + links)的转换,vue-d3-network负责力导向渲染与交互。通过本文,你应当已经掌握了这套工程的完整生命周期:
- 以Node >= 20.0.0为前提,用
npm install安装依赖; - 用
npm run serve启动热重载开发服务器; - 在
src/components/Nodes.vue中补全createLinks(),把信件数据的from/to映射为{ sid, tid }连线; - 用
npm run lint维持代码规范,用npm run build产出可直接部署的静态产物。
在此基础上,参考 solution 版本 对照检查,再动手完成「自建社交网络」的 作业,你就能把本课学到的「选择合适图表、为可读性设计、用交互增强表达」真正落到自己的可视化作品里。
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考