【问题标题】:Preserve d3 zoom state when changing out SVG contents?更改 SVG 内容时保留 d3 缩放状态?
【发布时间】:2026-02-15 09:30:02
【问题描述】:

我正在使用 d3 渲染一些东西,并使用 d3.zoom 用鼠标进行缩放。它可以工作,但我还需要定期更改 svg 的内容(进行完整的$('svg').html($('svg').html()) 调用,因为我的 SVG 包含 HTML)。

问题是当我这样做时,我失去了缩放状态。我试图通过存储缩放变换并在更新后重新应用它来跟踪它,但它不起作用。

Here's a pen 我的尝试,使用 dagre-d3 示例图。

简而言之,这就是我正在做的事情:

let transform;

function dag(){
  // ... set up stuff here

  var svg = d3.select("svg"),
      inner = svg.select("g");

  // Set up zoom support
  var zoom = d3.zoom().on("zoom", function() {
        //store transform
        transform = d3.event.transform
        inner.attr("transform", d3.event.transform);
      });
  svg.call(zoom);

  // render graph
  new dagreD3.render()(inner, g);

  // Center the graph
  var initialScale = 0.75;
  svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));

  svg.attr('height', g.graph().height * initialScale + 40);
}

setInterval(() => {
  // simulate reloading content
  dag()
  console.log('render again')
  //try and apply saved transform state
  transform && inner.attr("transform", transform);
}, 2000)

【问题讨论】:

  • 这就是你想要的吗? codepen.io/anon/pen/MBwBYY?editors=0011(每次绘制间隔时它仍然居中,但我猜你想要这样?)如果这是你想要的,那是因为你用默认的'initialScale'重新缩放,你需要更新那个。检查第 63 行。
  • @REEE 我不希望它居中,但删除该代码可以解决问题。谢谢你的帮助,你能写一个答案让我接受吗?
  • 太棒了,很高兴我能帮上忙。我用更多的解释写了答案,以防万一其他人遇到类似的问题。祝你项目的其余部分好运:)。

标签: javascript d3.js dagre-d3 dagre


【解决方案1】:

在缩放函数中设置变换后,再次使用'initialScale'变量设置svg比例,问题可以在这里看到:

  // Center the graph
  var initialScale = 0.75;
  svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));

要解决这个问题,您需要根据 svg 的当前比例变换更改“initialScale”变量中的值。如此处所示:

  // Center the graph
  var initialScale = (typeof transform != 'undefined') ? transform.k : 0.75;
  svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));

带有修复的代码的codepen:https://codepen.io/anon/pen/MBwBYY?editors=0011

【讨论】: