You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:01:12