javascript - 使用新数据更新 d3 图表

标签 javascript d3.js

我想用新数据更新条形图,我查看了这个问题: How to update d3.js bar chart with new data 但这对我不起作用。可能是因为我不知道在我的代码中将 exit().remove() 函数放在哪里。我试着把这条线

svg.selectAll("rect").exit().remove();

在创建栏部分下方,但它只是删除了所有标签。然后,如果我把它放在创建标签部分之后,它会完全删除图表。如何让更新按钮用新数据更改图表?

    function draw(data) {
        //Width and height
        var w = 250;
        var h = 250;

        var xScale = d3.scale.ordinal()
                        .domain(d3.range(data.length))
                        .rangeRoundBands([0, w], 0.05);

        var yScale = d3.scale.linear()
                        .domain([0, d3.max(data)])
                        .range([0, h]);

        //Create SVG element
        var svg = d3.select("#chart")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        //Create bars
        svg.selectAll("rect")
           .data(data)
           .enter()
           .append("rect")
           .attr("x", function(d, i) {
                return xScale(i);
           })
           .attr("y", function(d) {
                return h - yScale(d);
           })
           .attr("width", xScale.rangeBand())
           .attr("height", function(d) {
                return yScale(d);
           })
           .attr("fill", "steelblue");

        //Create labels
        svg.selectAll("text")
           .data(data)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("text-anchor", "middle")
           .attr("x", function(d, i) {
                return xScale(i) + xScale.rangeBand() / 2;
           })
           .attr("y", function(d) {
                return h - yScale(d) + 14;
           })
           .attr("font-family", "sans-serif")
           .attr("font-size", "11px")
           .attr("fill", "white");

        };

        function update() {
            var data = [ 25, 22, 18, 15, 13 ];
            draw(data);
        }

        var data = [ 21, 3, 5, 21, 15 ];

        window.onload = draw(data);

最佳答案

使用 d3v3(正如我从您使用此版本的代码中看到的那样),您应该以这种方式更新您的图表:

update 函数中为 yScale 设置新域:

function update(newData) {
  yScale.domain([0, d3.max(newData)]);

之后,使用 selectAll("rect").data(newData) 应用新选择,将选择存储在 rects 变量中并为适当的属性设置新值(如果你不想要动画效果,删除 .transition() .duration(300):

var rects = d3.select("#chart svg")
  .selectAll("rect")
  .data(newData);

// enter selection
rects
  .enter().append("rect");

// update selection
rects
  .transition()
  .duration(300)
  .attr("y", function(d) {
    return h - yScale(d);
  })
  .attr("height", function(d) {
    return yScale(d);
  })

exit方法退出选择:

rects
  .exit().remove();

text 做同样的事情。我重写了您的代码,请查看下面隐藏片段中的示例:

var myData = [21, 3, 5, 21, 15];
//Width and height
var w = 250;
var h = 250;
var yScale = null;

function draw(initialData) {
  var xScale = d3.scale.ordinal()
    .domain(d3.range(initialData.length))
    .rangeRoundBands([0, w], 0.05);

  yScale = d3.scale.linear()
    .domain([0, d3.max(initialData)])
    .range([0, h]);

  //Create SVG element
  var svg = d3.select("#chart")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

  svg.selectAll("rect")
    .data(initialData)
    .enter()
    .append("rect")
    .attr("x", function(d, i) {
      return xScale(i);
    })
    .attr("y", function(d) {
      return h - yScale(d);
    })
    .attr("width", xScale.rangeBand())
    .attr("height", function(d) {
      return yScale(d);
    })
    .attr("fill", "steelblue");

  svg.selectAll("text")
    .data(initialData)
    .enter()
    .append("text")
    .text(function(d) {
      return d;
    })
    .attr("text-anchor", "middle")
    .attr("x", function(d, i) {
      return xScale(i) + xScale.rangeBand() / 2;
    })
    .attr("y", function(d) {
      return h - yScale(d) + 14;
    })
    .attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "white");
}


function update(newData) {
  yScale.domain([0, d3.max(newData)]);

  var rects = d3.select("#chart svg")
    .selectAll("rect")
    .data(newData);

  // enter selection
  rects
    .enter().append("rect");

  // update selection
  rects
    .transition()
    .duration(300)
    .attr("y", function(d) {
      return h - yScale(d);
    })
    .attr("height", function(d) {
      return yScale(d);
    })

  // exit selection
  rects
    .exit().remove();

  var texts = d3.select("#chart svg")
    .selectAll("text")
    .data(newData);

  // enter selection
  texts
    .enter().append("rect");

  // update selection
  texts
    .transition()
    .duration(300)
    .attr("y", function(d) {
      return h - yScale(d) + 14;
    })
    .text(function(d) {
      return d;
    })

  // exit selection
  texts
    .exit().remove();
}

window.onload = draw(myData);

setInterval(function() {
  var data = d3.range(5).map(function() {
    return parseInt(Math.random() * 20 + 1);
  });

  update(data);
}, 3000)
<div id="chart"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>

关于javascript - 使用新数据更新 d3 图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47196592/

相关文章:

javascript - 你如何在 Nuxt.js 中导入 three.js OBJLoader? "Cannot use import statement outside a module"

javascript - 我如何在 jQuery 插件代码中执行回调

javascript - d3 rect 没有显示

javascript - 如何按州和行/列在气泡图中定位气泡

javascript - 如何进行多个 api 调用以在 d3 图表中显示单个数据

javascript - 使用 Cypress.js 测试 D3.js 拖动事件

javascript - AJAX 提交和 500 服务器错误

javascript - 使用 angularJS 将动态列绑定(bind)到表

javascript - 组合来自不同变量的数组以随机填充 javascript

javascript - 如何在 d3 js 中正确使用 SVG 中的 Use 标签?