如何在D3.js最新版本中为力导向图应用缩放变换?
D3.js v7 缩放功能实现方案
核心修改点
- 创建统一容器组:将所有可视化元素(节点、连线)放入同一个
<g>容器,避免直接操作SVG根元素的transform属性 - 更新zoomed函数:利用事件对象的
transform属性,将缩放变换应用到容器组上
修改后的完整代码
const width = 1000 const height = 400 const node_data = Array.from({ length: 5 }, () => ({ group: Math.floor(Math.random() * 3), })) const edge_data = Array.from({ length: 10 }, () => ({ source: Math.floor(Math.random() * 5), target: Math.floor(Math.random() * 5), value: Math.floor(Math.random() * 10) + 1, })) const links = edge_data.map((d) => ({ ...d })) const nodes = node_data.map((d, index) => ({ id: index, ...d })) const color = d3.scaleOrdinal(d3.schemeCategory10) function zoomed(event) { // 把缩放变换应用到容器组 gContainer.attr('transform', event.transform); } const svg = d3.select('#chart').call(d3.zoom().on('zoom', zoomed)) // 创建统一容器,存放所有可视化元素 const gContainer = svg.append('g'); const simulation = d3 .forceSimulation(nodes) .force( 'link', d3 .forceLink(links) .id((d) => d.id) .distance((d) => 100) ) .force('charge', d3.forceManyBody()) .force('center', d3.forceCenter(width / 2, height / 2)) .on('tick', ticked) // 将连线组挂载到容器下 const link = gContainer .append('g') .attr('stroke', '#999') .attr('stroke-opacity', 0.6) .selectAll() .data(links) .join('line') .attr('stroke-width', (d) => Math.sqrt(d.value)) // 将节点组挂载到容器下 const node = gContainer .append('g') .attr('stroke', '#fff') .attr('stroke-width', 1.5) .selectAll() .data(nodes) .join('circle') .attr('r', 16) .attr('fill', (d) => color(d.group)) node.append('title').text((d) => `hello ${d.id}`) function ticked() { 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) } node.call(d3.drag().on('start', dragstarted).on('drag', dragged).on('end', dragended)) 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 }
.graph { width: 1000px; height: 400px; }
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script> <svg id="chart" class="graph"></svg>
关键说明
- 容器组的作用:所有节点和连线都挂载在
gContainer下,缩放时仅对该组应用变换,不会干扰力导向模拟的坐标计算 - D3 v7 zoom事件特性:
zoomed函数接收的事件对象中,event.transform直接包含当前缩放、平移信息,无需手动解析属性值,直接通过attr方法应用即可 - 版本兼容性:完全适配D3.js v7,摒弃了旧版本中
d3.event的使用方式,符合最新API规范
内容的提问来源于stack exchange,提问作者Eric G
相关产品推荐
相关产品推荐

