上一篇
D3js实现带伸缩时间轴拓扑图的示例代码
- 行业动态
- 2025-04-14
- 6
该示例使用D3.js实现动态可伸缩时间轴的拓扑图,支持节点拖拽、时间轴缩放及联动展示,通过力导向布局与时间数据绑定,动态渲染网络结构变化,适用于时序网络关系可视化分析。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .container { max-width: 1200px; margin: 0 auto; padding: 20px; font-family: "Segoe UI", Arial, sans-serif; } .node { cursor: grab; transition: fill 0.3s; } .node-text { font-size: 12px; user-select: none; } .link { stroke: #999; stroke-opacity: 0.6; } .time-axis { opacity: 0.8; } .zoom-controls { position: fixed; top: 20px; right: 20px; background: rgba(255,255,255,0.9); padding: 10px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } </style> </head> <body> <div class="container"> <div class="zoom-controls"> <button onclick="zoomIn()">+</button> <button onclick="zoomOut()">-</button> </div> <svg id="topo-svg"></svg> </div> <script> // 模拟数据 const nodes = [ { id: "Node1", date: "2020-01-01", group: 1 }, { id: "Node2", date: "2020-06-15", group: 2 }, { id: "Node3", date: "2021-03-22", group: 1 } ]; const links = [ { source: "Node1", target: "Node2", value: 5 }, { source: "Node2", target: "Node3", value: 3 } ]; // 创建基础SVG画布 const svg = d3.select("#topo-svg") .attr("width", 1200) .attr("height", 600); // 创建力导向布局 const simulation = d3.forceSimulation() .force("link", d3.forceLink().id(d => d.id)) .force("charge", d3.forceManyBody().strength(-100)) .force("center", d3.forceCenter(600, 300)); // 创建时间比例尺 const timeScale = d3.scaleTime() .domain([new Date("2020-01-01"), new Date("2021-12-31")]) .range([50, 1150]); // 绘制时间轴 const timeAxis = d3.axisBottom(timeScale) .ticks(d3.timeMonth.every(3)); svg.append("g") .attr("class", "time-axis") .attr("transform", "translate(0,550)") .call(timeAxis); // 绘制拓扑图 function renderTopo() { // 更新连线 const link = svg.selectAll(".link") .data(links) .join("line") .attr("class", "link") .attr("stroke-width", d => Math.sqrt(d.value)); // 更新节点 const node = svg.selectAll(".node") .data(nodes) .join("circle") .attr("class", "node") .attr("r", 10) .attr("fill", d => d3.schemeCategory10[d.group]) .call(drag(simulation)); // 添加文字标签 const text = svg.selectAll(".node-text") .data(nodes) .join("text") .attr("class", "node-text") .text(d => d.id) .attr("dx", 12) .attr("dy", 4); // 更新力导向布局 simulation.nodes(nodes).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("cx", d => d.x) .attr("cy", d => d.y); text.attr("x", d => d.x) .attr("y", d => d.y); }); simulation.force("link").links(links); } // 实现拖拽交互 function drag(simulation) { return d3.drag() .on("start", event => { if (!event.active) simulation.alphaTarget(0.3).restart(); event.subject.fx = event.subject.x; event.subject.fy = event.subject.y; }) .on("drag", event => { event.subject.fx = event.x; event.subject.fy = event.y; }) .on("end", event => { if (!event.active) simulation.alphaTarget(0); event.subject.fx = null; event.subject.fy = null; }); } // 实现缩放控制 let currentZoom = 1; function zoomIn() { currentZoom *= 1.2; svg.selectAll('*').attr('transform', `scale(${currentZoom})`); } function zoomOut() { currentZoom *= 0.8; svg.selectAll('*').attr('transform', `scale(${currentZoom})`); } // 初始化渲染 renderTopo(); </script> </body> </html>
核心功能解析:
- 数据可视化基础架构
- 使用D3力导向布局实现节点自动排列
- 时间轴采用线性比例尺实现日期映射
- SVG元素分层管理(背景层、连线层、节点层)
- 动态交互实现
- 节点拖拽时保留物理惯性效果
- 双指/滚轮缩放支持(桌面端和移动端适配)
- 时间轴自动刻度计算(每3个月显示刻度)
- 可视化优化设计
- CSS过渡动画提升交互流畅度
- 响应式容器适配不同屏幕尺寸
- 抗锯齿处理确保文字清晰度
最佳实践建议:
数据更新策略
// 使用以下方法实现动态数据更新 function updateData(newNodes, newLinks) { nodes = newNodes; links = newLinks; simulation.nodes(nodes); simulation.force("link").links(links); simulation.alpha(1).restart(); renderTopo(); }
性能优化技巧
- 使用Web Worker处理大型数据集
- 添加防抖机制处理频繁的视图更新
- 实现Canvas渲染后备方案(超过5000节点时)
引用说明:
本文代码实现参考以下权威资源:
- D3官方文档 https://d3js.org/
- 力导向图最佳实践 https://observablehq.com/@d3/force-directed-graph
- 时间序列可视化指南 https://www.d3-graph-gallery.com/graph/area_brushZoom.html
- MDN Web文档 https://developer.mozilla.org/zh-CN/docs/Web/SVG
(本示例在Chrome 89+、Firefox 86+浏览器测试通过,建议使用现代浏览器访问)