【问题标题】:D3 updating bar chart with new data set cause update issue由于更新问题,D3 使用新数据集更新条形图
【发布时间】:2014-03-05 21:51:23
【问题描述】:

条形图的渲染可以很好地使用默认给定数据。问题发生在按钮单击上,这也应该导致获取新数据集。更新 x 轴 y 轴效果很好,但渲染数据会导致问题。

首先我会尝试删除所有以前添加的矩形,然后添加新的数据集。但是所有新的矩形元素都被添加到错误的位置,因为没有对旧矩形的引用。

这是代码,重绘在代码的末尾。

http://jsfiddle.net/staar2/wBNWK/9/

 var data = JSON.parse('[{"hour":0,"time":147},{"hour":1,"time":0},{"hour":2,"time":74},{"hour":3,"time":141},{"hour":4,"time":137},{"hour":5,"time":210},{"hour":6,"time":71},{"hour":7,"time":73},{"hour":8,"time":0},{"hour":9,"time":68},{"hour":10,"time":70},{"hour":11,"time":0},{"hour":12,"time":147},{"hour":13,"time":0},{"hour":14,"time":0},{"hour":15,"time":69},{"hour":16,"time":67},{"hour":17,"time":67},{"hour":18,"time":66},{"hour":19,"time":0},{"hour":20,"time":0},{"hour":21,"time":66},{"hour":22,"time":210},{"hour":23,"time":0}] ');

  var w = 15,
      h = 80;

  var xScale = d3.scale.linear()
      .domain([0, 1])
      .range([0, w]);

  var yScale = d3.scale.linear()
      .domain([0, d3.max(data, function (d) {
          return d.time;
      })])
      .rangeRound([5, h]);

  var xAxis = d3.svg.axis()
      .scale(xScale)
      .orient("bottom")
      .ticks(5);

  var yAxis = d3.svg.axis()
      .scale(yScale)
      .orient("left");

  var chart = d3.select("#viz")
    .append("svg")
    .attr("class", "chart")
    .attr("width", w * data.length - 1)
    .attr("height", h);

  chart.selectAll("rect")
    .data(data)
    .enter().append("rect")
    .attr("x", function(d, i) {
      return xScale(i) - 0.5;
    })
    .attr("y", function(d) {
      return h - yScale(d.time) - 0.5;
    })
    .attr("width", w)
    .attr("height", function(d) {
      return yScale(d.time);
    });

  chart.selectAll("text")
   .data(data)
   .enter()
   .append("text")
   .text(function(d) {
      if (d.time > 10) {
        return Math.round(d.time);
      }
   })
   .attr("font-family", "sans-serif")
   .attr("font-size", "11px")
   .attr("fill", "#FFF")
   .attr("text-anchor", "middle")
   .attr("x", function(d, i) {
        return xScale(i) + w / 2;
   })
   .attr("y", function(d) {
        return h - yScale(d.time) - 0.5 + 10;
   });

  chart.append("g")
    .attr("transform", "translate(0," + (h) + ")")
    .call(xAxis);

    function redraw() {

      // This the part where the incoming data set also changes, which means the update to x-axis y-axis, labels

      yScale.domain([0, d3.max(data, function (d) {
        return d.time;
      })]);

      var bars = d3.selectAll("rect")
        .data(data, function (d) {
           return d.hour;
        });

      bars
         .transition()
         .duration(500)
         .attr("x", w)  // <-- Exit stage left
         .remove();

      d3.selectAll("rect") // This is actually empty
        .data(data, function (d) {
          return d.hour;
        })
        .enter()
        .append("rect")
        .attr("x", function(d, i) {
          console.log(d, d.day, xScale(d.day));

          return xScale(d.day);
        })
        .attr("y", function(d) {
          return yScale(d.time);
        })
        .attr("width", w)
        .attr("height", function (d) {
          return h - yScale(d.time);
        });
    }

    d3.select("button").on("click", function() {
      console.log('Clicked');

      redraw();
    });

【问题讨论】:

  • 您似乎正在删除所有条形图,然后尝试立即将它们添加回来。你究竟想做什么?只更新条的位置?
  • 目前的例子不是最好的,但是我想用新的数据集更新数据,这意味着需要添加更多的矩形。基本上,如果第一个数据集在更新后包含大约 23 列,则应该有 31 列。问题是我将如何附加丢失的 rect 项?
  • 如果xScale改成d3.scale.ordinal()可能会更方便
  • 是的,你能解释一下为什么会更容易吗?

标签: javascript d3.js bar-chart


【解决方案1】:

同意 Sam(尽管还有一些问题,例如使用 remove() 而不使用 exit() 等),我将其发布是因为我在清理代码和应用更新时正在使用它图案。这是FIDDLE,对我所做的代码进行了更改。我只更改了前几个数据点,但这应该能让你继续前进。

var data2 = JSON.parse('[{"hour":0,"time":153},{"hour":1,"time":10},{"hour":2,"time":35},{"hour":3,"time":150},

更新:根据请求,添加逻辑以考虑使用新数据进行更新。 UPDATED FIDDLE.

【讨论】:

  • 干得好,是的,您的示例有效,并且在更新后退出的 rect 元素也会被删除。但是我缺少的用例是向图表添加更多数据点,让我们再添加两个小时参数,然后在更新后应该添加更多矩形。 jsfiddle.net/UjT8d
  • 为此,需要进行一些其他更改,例如 1) 将 enter() 选择添加到组合中,以及 2) 键入时间以帮助更新。更新FIDDLE
【解决方案2】:

由于您将相同的数据绑定到bars,因此enter 选择为空。删除现有条形后,appendenter 选择中的每个数据点创建一个新条形 - 这又是空的。如果您有不同的数据,则应附加条形。

如果您还没有阅读过它,general update pattern 是了解此类内容的绝佳资源。

【讨论】:

    猜你喜欢
    • 2019-08-24
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    相关资源
    最近更新 更多