Сохранить состояние масштабирования d3 при изменении содержимого SVG?

Я рендеринг что-то с помощью d3, и использую d3.zoom чтобы увеличить с помощью мыши. Это работает, но мне также нужно периодически менять содержимое SVG (делает полный $('svg').html($('svg').html()) звоните, потому что мой SVG содержит HTML).

Проблема в том, что когда я делаю это, я теряю состояние масштабирования. Я пытался отследить это, сохранив трансформацию зума и применив ее после обновления, но это не работает.

Вот ручка с моей попыткой, на примере диаграммы 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)

1 ответ

Решение

Масштаб SVG устанавливается снова с помощью переменной initialScale после того, как преобразование установлено в функции масштабирования, проблему можно увидеть здесь:

  // 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));

Чтобы обойти это, вам нужно изменить значение в переменной 'initialScale' на основе текущего масштабного преобразования SVG. Как видно здесь:

  // 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));

Кодовая часть кода с исправлением: https://codepen.io/anon/pen/MBwBYY?editors=0011

Другие вопросы по тегам