
简介networkMap V1.0 是一套基于 ECharts 的网络拓扑可视化组件面向需要展示设备节点与连线关系的前端开发者适用于运维监控、网络规划、系统架构展示等场景。组件封装了拓扑图绘制与线条布局支持节点与边的样式定制并内置点击事件监听可在点击节点时直接调用后端接口同时支持屏幕自适应适配不同分辨率。资源共 7 个文件包括 3 个 JS核心逻辑与图表库、2 个 PNG效果示意图或图标、1 个 HTML可直接运行的拓扑示例页和 1 个 TXT使用说明压缩包整体约 254KB结构清晰便于快速集成到现有项目中。目前已有 1162 人学习浏览适合需要快速搭建交互式网络拓扑图的开发者参考。通过该资源可获得完整的组件代码、使用说明与示例页面能大幅减少从零封装 ECharts 的时间并可直接基于示例改造二次开发。1. networkMap 是什么一个用 ECharts 手搓的网络拓扑可视化方案如果你手里有一堆节点和连线数据想一眼看出设备之间的链路关系、流量走向或依赖层级那 networkMap 就是个非常对口的开箱即用地图。它不是那种拖拽生成图表的工具而是一个基于 ECharts 的 graph 类型、用纯 JS 实现的网络拓扑图解析项目。我拆完这个包最大的感受是它把 ECharts 里最容易被忽视的 graph 系列玩明白了线段、节点、标签、涟漪动画都配齐了数据一换就能变成自己的网络监控大屏。适合两类人一类是做运维或 IoT 可视化、想快速出拓扑图的开发者另一类是刚接触 ECharts、想找个完整 graph 示例当跳板的同学。2. 项目结构与技术选型为什么说它是 ECharts graph 的教科书2.1 解压后你看到的文件格局打开 networkMap V1.0 压缩包里面不是一个被 webpack 裹得严严实实的大工程而是一个能直接双击 index.html 就跑的静态项目。目录结构大致如下networkMap/ ├── index.html # 入口页面承载画布和工具栏 ├── css/ │ └── style.css # 布局、图例、弹窗样式 ├── js/ │ ├── echarts.min.js # ECharts 核心库 │ ├── networkMap.js # 核心逻辑数据装配与图表实例化 │ └── data.js # 独立的拓扑数据源节点与连线在这里改 └── assets/ └── images/ # 节点图标等静态资源这种「数据、逻辑、展示」三层分离的写法对于非工程化项目来说非常友好。你不需要安装 Node、不需要配打包器浏览器直接加载就能看到效果要改拓扑结构时只需打开data.js编辑 JSON 数组。对想快速做原型验证的开发者来说这种零依赖的目录设计比一上来就拉 Vue 全家桶要省心得多。2.2 技术栈解读ECharts 的 graph 系列为什么适合网络拓扑网络拓扑图和普通的折线图、柱状图最大的不同在于节点有坐标、有层级连线有方向、有权重而且往往需要交互——点一个节点高亮与之关联的链路。ECharts 的graph系列正好覆盖了这些需求。它支持force布局或者自定义坐标支持links定义源节点和目标节点还能通过categories给节点分组着色。networkMap 这个项目用的是 ECharts 的标准 graph 类型核心配置项集中在series里配合tooltip、legend和roam实现缩放漫游。2.3 核心配置骨架series-graph 的必备参数下面这段是 networkMap 里最核心的 series 配置骨架我从networkMap.js里提炼出来去掉了业务噪音保留关键参数option { tooltip: {}, legend: [{ data: categories.map(c c.name), bottom: 10 }], series: [{ type: graph, layout: force, // 使用力导向布局自动计算节点位置 roam: true, // 允许拖拽和缩放 draggable: true, // 节点可拖动 data: nodes.map(n ({ id: n.id, name: n.name, category: n.category, symbolSize: n.size, symbol: n.symbol || circle, itemStyle: { color: n.color } })), links: links.map(l ({ source: l.source, target: l.target, value: l.value, lineStyle: { width: l.value / 10, // 线宽正比于链路权重 curveness: 0.2, type: l.type || solid } })), categories: categories.map(c ({ name: c.name, itemStyle: { color: c.color } })), force: { repulsion: 300, // 节点间斥力值越大节点越分散 edgeLength: 120 // 理想边长链路越长布局越松 } }] };这里有几个参数值得留意。layout: force让节点自动分布在画布上省去手工算坐标的麻烦roam: true开启后用户可以缩放平移这在网络规模大时非常实用。links里的value字段不只是展示用的我还用它映射了线宽一眼就能看出哪条链路流量大。curveness: 0.2给连线加了轻微弧度当两个节点间有多条链路时能避免重叠。这些配置组合起来就是一张能交互的拓扑图。2.4 数据格式说明data.js 里到底该写什么networkMap 把数据独立成data.js这是一个非常贴心的设计。你要换一张拓扑图完全不用碰逻辑代码。数据格式分三块节点数组、连线数组、分类数组。节点必须有唯一的idcategory对应分类下标symbolSize控制节点大小。连线用source和target指向节点 id。下面是一个缩略示例var nodes [ { id: router1, name: 核心路由器, category: 0, size: 50, symbol: image://assets/images/router.png }, { id: switch1, name: 汇聚交换机, category: 1, size: 40 }, { id: host1, name: 服务器A, category: 2, size: 30 } ]; var links [ { source: router1, target: switch1, value: 80, type: solid }, { source: switch1, target: host1, value: 20, type: dashed } ]; var categories [ { name: 核心层, color: #ff7f50 }, { name: 汇聚层, color: #87ceeb }, { name: 接入层, color: #32cd32 } ];注意symbol字段可以用image://前缀加载本地图片这就是 assets 目录存在的意义。如果没有图片直接删掉symbol字段就会回退成圆形。size是我自定义的字段在装配数据时映射到symbolSize。这里的分类三层模型是最典型的网络拓扑分层法你在二次开发时也可以改成「园区—楼栋—机房—机柜」的层级。3. 核心模块拆解一个请求从进入到返回的完整链路3.1 页面加载与 ECharts 实例化networkMap 的入口是index.html它只做两件事引入样式和脚本、摆放承载图表的div。打开文件可以看到关键的 DOM 结构和脚本引入顺序div idmapContainer stylewidth: 100%; height: 700px;/div script srcjs/echarts.min.js/script script srcjs/data.js/script script srcjs/networkMap.js/script这里的引入顺序有讲究echarts.min.js必须先加载否则后面两个文件里引用echarts对象会直接报错data.js在networkMap.js之前是因为后者要读取前者定义的全局变量nodes、links、categories。页面加载完成后networkMap.js会执行初始化逻辑核心只有几行var chartDom document.getElementById(mapContainer); var myChart echarts.init(chartDom); myChart.setOption(buildOption());echarts.init接收一个 DOM 节点这里是 id 为mapContainer的 div。buildOption函数把原始数据转换成前面看到的option结构。这样设计的好处是data.js里存的是「业务数据」networkMap.js里存的是「图表配置」两者解耦。我在做实际项目时也沿用了这个习惯数据归数据展示归展示。3.2 节点渲染与分类着色节点是网络拓扑图的第一视觉要素。networkMap 里的buildOption对节点做了几层加工首先是打散data.js里的nodes数组把size映射到symbolSize把color映射到itemStyle.color其次是关联category让同类的节点共享颜色。分类色是在categories数组里定义的这样做的好处是更新一个分类颜色所有属于该分类的节点自动变色不用逐个改。3.3 连线渲染与权重可视化链路是网络拓扑的血管。networkMap 对links的处理最值得学习的地方是权重映射链路的value字段被用来计算线宽和透明度数值越大线越粗、颜色越深。在真实网络监控里这个value可以直接替换成实时带宽利用率这样拓扑图就变成了流量热力图。第二点是type字段支持solid、dashed两种线型通常用来区分物理链路和逻辑链路。3.4 交互机制点击、拖拽与缩放一个能看的拓扑图不难一个能用的拓扑图必须支持交互。networkMap 通过roam开启了缩放和平移通过draggable让节点可拖拽。ECharts 的 graph 在开启force布局后拖拽一个节点相关链路会跟着弹性伸缩这个体验非常接近真实物理模拟。代码层面还注册了click事件点击节点时弹出该节点的详细信息这个我们放在后面的排查章节里细说。4. 避坑与常见问题拆 networkMap 时我踩过的五个坑4.1 图表不显示控制台报错Cannot read property init of undefined现象双击 index.html 打开一片空白F12 看到echarts is not defined。原因echarts.min.js加载失败或引入顺序错了。解决确认js目录下有 ECharts 文件检查 script 标签顺序ECharts 必须在自定义脚本之前如果用本地文件方式访问还需要留意浏览器对本地file://协议下跨域请求的限制虽然这个项目全是本地文件不会有跨域问题但有个别浏览器会拦截本地 JS 文件加载这时用轻量级服务器起个静态服务更稳妥。4.2 节点全部挤在左上角布局乱成一团现象nodes 数据有几十个打开后所有节点堆在坐标 (0,0) 附近完全看不出拓扑。原因layout没有设置成force或者force配置里的repulsion和edgeLength没给。解决确认series.layout为force如果是自定义布局需要在每个节点 data 里手动写x、y。这个项目里用的是 force不需要给坐标但如果你改成了layout: none就必须要坐标了。4.3 链路显示为直线且互相重叠看不清谁连谁现象当两个节点之间存在多条链路时所有线挤成一条直线。原因lineStyle.curveness没设置或值得为 0。解决给每条 link 的lineStyle加curveness: 0.2如果两条线方向相反还可以配合link.offset或调整数组顺序让曲线往不同方向弯。networkMap 里已经给了 0.2 的默认值如果你自己拼数据忘了写就会出现这个现象。4.4 节点图片不显示显示成灰色方块现象给节点配了symbol: image://assets/images/router.png但图上显示是个破碎的图标。原因图片路径写错或者资源文件没打包进部署目录。解决先确认 assets/images 下有这个文件接着注意image://前缀后面跟的是相对路径这个路径是相对于 index.html 的不是相对于 JS 文件的最后检查图片格式SVG 和 PNG 通常都支持但个别环境下 base64 格式更保险。4.5 点击节点没有反应事件绑了个寂寞现象图形能显示节点也能拖动但点击后没有任何输出。原因绑定的 click 事件写在了setOption之前或者事件绑在了chart上但回调里访问了未定义的变量。解决先setOption再on(click, handler)回调参数params里取data.id时由于 data 里存的是对象需要用params.data.id而不是params.data直接作为 id。这段逻辑是排查最耗时的建议封装一个handleNodeClick函数在里面做防御性判断。5. 二次开发指南把静态拓扑改成实时监控大屏5.1 改造点一数据源换成接口实时刷新networkMap 的data.js是写死的静态数据但真实场景里拓扑数据需要跟着网络状态变。最常见的改造是删掉 script 引入data.js改成启动时通过 fetch 从后端拉取数据然后每隔几秒再拉一次。核心代码如下async function fetchTopology() { const res await fetch(/api/topology); const data await res.json(); myChart.setOption({ series: [{ data: data.nodes, links: data.links }] }, true); } setInterval(fetchTopology, 5000);注意setOption的第二个参数传了true意思是完全替换 series 数据而不是合并。这样每次接口返回全量数据时图上旧的节点和连线会被清掉再重新绘制。如果你只想增量更新某几个节点的状态就不要传true而是用myChart.setOption({ series: [{ data: newData }] })让 ECharts 按 id 做 diff 合并。这套逻辑是我在实际监控项目里验证过的能有效避免图表闪烁和旧节点残留。5.2 改造点二给节点增加状态颜色和涟漪动画网络拓扑图最实用的增强是让节点颜色反映设备健康状况。比如 ping 不通就标红CPU 过载就标橙。实现方式是在data.js的节点对象里加一个status字段然后在buildOption里根据status动态计算itemStyle.color。ECharts 的effect系列还支持涟漪特效适合标记重要节点series: [{ type: graph, data: nodes.map(n ({ ...n, symbolSize: n.status alarm ? 60 : 40, itemStyle: { color: n.status alarm ? #ff4500 : #32cd32 } })), effect: { show: true, symbolSize: 20, color: #ff4500, trailLength: 0.2 } }]effect配置会让节点像雷达波纹一样向外扩散告警节点一眼就能被发现。这个手段在故障排查时特别好用比盯着告警列表直观多了。注意effect默认只对symbolSize比较大的节点明显所以我把告警节点的尺寸同时放大了。5.3 改造点三双图联动与下钻当网络层级超过两层时一张图放不下所有节点。我的建议是把 networkMap 扩展成主从结构主图画核心层和汇聚层点击某个汇聚节点时下方或弹窗渲染一张子图显示它下面的接入层设备。这个下钻逻辑不复杂核心是复用buildOption传入不同的数据子集function drillDown(nodeId) { const subNodes allNodes.filter(n n.parentId nodeId); const subLinks allLinks.filter(l l.source nodeId || l.target nodeId); subChart.setOption(buildOption(subNodes, subLinks)); }这里需要你在数据模型里提前定义好parentId字段用来描述层级归属。networkMap 原始数据里没有这个字段所以我加了这段代码演示扩展思路。从我的经验看双图联动比单图塞几千个节点要实用得多浏览器渲染性能也能扛住。5.4 改造点四支持图例筛选和节点搜索ECharts 自带的 legend 组件可以按分类显隐但针对具体节点的搜索需要自己实现。一个轻量方案是在页面加一个输入框监听input事件遍历 nodes 找到名称匹配的节点然后通过dispatchAction高亮它function highlightNode(keyword) { const target nodes.find(n n.name.includes(keyword)); if (target) { myChart.dispatchAction({ type: highlight, seriesIndex: 0, dataIndex: nodeList.findIndex(n n.id target.id) }); } }高亮之后还可以配合focusNodeAdjacency这个 action 将关联链路也高亮起来让使用者快速看清这个节点连了谁。这套搜索加高亮组合拳做出来后拓扑图的可玩性会有质的提升。我从那以后每次做可视化项目都会强制走一遍静态改接口、状态改颜色、点击做下钻、搜索做联动这条改造链能少走很多弯路。希望这份 networkMap 拆解能帮你在二次开发时少踩几个坑。本文还有配套的精品资源点击获取