D3条形图更新

时间:2017-10-11 06:28:40

标签: d3.js

我正在学习D3并且在更新条形图时遇到问题

  let container = d3.select(this)

  let x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
  let y = d3.scaleLinear().rangeRound([height, 0])

  x.domain(data.map(function(d) {
    return d.x;
  }));

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

  // seems like everytime when there is a new data, a new "g" is appended
  let g = container
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  const gEnter = g.selectAll('.bar')
    .data(data)

  gEnter.exit().remove()

  gEnter.enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.x)
    })
    .attr("y", function(d) {
      return y(d.y)
    })
    .attr('fill', barColor)
    .attr("width", x.bandwidth())
    .attr("height", function(d) {
      return height - y(d.y)
    })

enter image description here

我的目标是每当有新数据进入时更新图表,上面的代码所做的就是在当前图表的顶部附加新图表。

不知怎的,我觉得我错过了一些微不足道的东西。

任何提示都会有所帮助,谢谢。

1 个答案:

答案 0 :(得分:0)

你应该移动

let g = container
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

更新函数,否则,每次执行此函数时都会创建一个新的g,在这个新的selectAll上创建一个g(并且在其中找不到任何内容) ,并对所有数据执行enter()选择。

您可以将结构更改为:

const svg = d3.select(this),
    container = svg.append('g')
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

let x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
let y = d3.scaleLinear().rangeRound([height, 0])

function update(data){

  x.domain(data.map(function(d) {
    return d.x;
  }));

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

  const gEnter = container.selectAll('.bar')
    .data(data)

  gEnter.exit().remove()

  gEnter.enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.x)
    })
    .attr("y", function(d) {
      return y(d.y)
    })
    .attr('fill', barColor)
    .attr("width", x.bandwidth())
    .attr("height", function(d) {
      return height - y(d.y)
    })
}

someAjaxCall().then(data => update(data))

您可以查看Mike Bostock撰写的example,了解如何整理代码。