【问题标题】:D3 circle pack - dynamic label updateD3圈子包-动态标签更新
【发布时间】:2013-11-19 16:32:11
【问题描述】:

我对 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 + "%" });
    }
  }
}

【问题讨论】:

    标签: javascript d3.js label transition circle-pack


    【解决方案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 + "%" });
    

    【讨论】:

    • 这正是我想要的;感谢您的快速响应!
    猜你喜欢
    • 2012-08-01
    • 1970-01-01
    • 2016-08-10
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    相关资源
    最近更新 更多