D3 circle pack - динамическое обновление этикетки

Я довольно новичок в кодировании в D3. Я работаю над круговой диаграммой почти в реальном времени, которая получает базовые данные от вызова ajax и изменяет размеры узлов на основе изменений в значениях данных. Задача, с которой я сталкиваюсь, вероятно, будет ужасно простой, но я пока не нашел достаточно похожего примера в Интернете, чтобы использовать его в качестве решения.

Когда я запускаю этот код, я знаю, что текстовые значения действительно передаются должным образом при изменении данных. Однако происходит следующее: код продолжает добавлять текстовые теги к узлам svg "g" (с обновленными значениями), а не изменяет существующий элемент для отображения обновленного значения. Результатом является многослойный текстовый беспорядок в середине иначе привлекательного пузыря.

Я пытался использовать d3.exit().remove() безрезультатно - возможно, что я неправильно использовал это и что это действительно подходящая техника для применения.

Будет ли кто-то готов дать несколько советов о том, как мне выполнить 2 конкретные вещи:

1) Я хотел бы повторно использовать существующие "текстовые" элементы вместо удаления + добавления, если это не практично.

2) Я хотел бы обновить значения существующего "текстового" элемента новыми данными, не обновляя страницу.

Полный код файла.js приведен ниже. Я знаю, что могу использовать "svg" вместо "svg: svg" и т. Д., Но я еще не дошел до стадии очистки этого файла.

var Devices = {
  setup_devices : function() {
  var r = 500,
    format = d3.format(",d"),
    fill = d3.scale.category10();

  var bubble = d3.layout.pack()
    .sort(null)
    .size([r, r])
    .padding(1.5);

  var chart = d3.select("#device_info").append("svg:svg")
    .attr("width", r)
    .attr("height", r)
    .attr("class", "bubble")
    .append("svg:g")
    .attr("transform", "translate(2, 2)");

  var tip = d3.tip()
    .attr('class', 'd3-tip')
    .offset([-10, 0])
    .html(function(d) {
      return "<strong>Device:</strong> <span style='color:red'>" + d.name + "</span>";
    });

  chart.call(tip);

  setInterval(function() {

    console.log("Devices Refreshing");

    $.ajax({
      type: "GET",
      url: "/devices",
      dataType: "json",
      beforeSend: function() {
      },
      error: function( jqXHR, textStatus, thrownError ) {
        return true;
      },
      success: function(data) {
        update(data);
        return true;
      }
    });

    d3.timer.flush();

  }, 2000);


  function update(data) {

    var updated = chart.data([data]).selectAll("g.node")
      .data(bubble.nodes);

    updated.enter().append("svg:g")
      .attr("class", "node")
      .attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
      })
      .attr("data-name", function(d) {
        return d.name;
      })
      .attr("data-device", function(d) {
        return d.device_id;
      })
      .on('mouseover', tip.show)
      .on('mouseout', tip.hide)
      .append("svg:circle")
        .attr("r", function(d) { return d.r; })
        .style("fill", function(d) { return fill(d.name); })
        .attr("text-anchor", "middle")
        .attr("dy", ".3em")
        .text(function(d) { return d.value + "%" });

    updated.append("svg:text")
      .attr("text-anchor", "middle")
      .attr("dy", ".3em")
      .text(function(d) { return d.value + "%" });

    updated.transition()
      .duration(1000)
      .attr("class", "node")
      .attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
      });

    updated.select("circle").transition()
      .duration(1000)
      .attr("r", function(d) { return d.r; })
      .text(function(d) { return d.value + "%" });
    }
  }
}

1 ответ

Решение

Вам просто нужно обрабатывать выбор ввода и обновления отдельно - к добавляемой выборке ввода, для выбора обновления вы повторно используете существующие элементы.

var enterGs = updated.enter().append("svg:g")
  .attr("class", "node")
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  })
  .attr("data-name", function(d) {
    return d.name;
  })
  .attr("data-device", function(d) {
    return d.device_id;
  })
  .on('mouseover', tip.show)
  .on('mouseout', tip.hide);

enterGs.append("circle");
enterGs.append("text")
  .attr("text-anchor", "middle")
  .attr("dy", ".3em");

updated.select("circle")
    .attr("r", function(d) { return d.r; })
    .style("fill", function(d) { return fill(d.name); });

updated.select("text")
    .text(function(d) { return d.value + "%" });
Другие вопросы по тегам