d3分组条形图更新模式不起作用

时间:2017-11-09 12:01:15

标签: javascript d3.js

在我试图掌握这一点的时候已经好几天了。到目前为止,我也在研究类似的问题而没有任何进展。

我有一个简单的分组条形图。我能够第一次绘制它,但没有成功更新它。如果我尝试让图表更新自己,它只会添加新数据。

我认为问题出在内部选择组的数据推导中。

代码:

// .chart -> .group -> .bar
// each group has 2 bars: one for data 'in' and another for 'out'
var data = [
  { "in" : 0, "out" : 40 },
  { "in" : 10, "out" : 39 },
  { "in" : 20, "out" : 40 }
];

var chart = d3.select('.chart');
var groupsSelection = chart.selectAll('.group');
var xScale = d3.scaleLinear().range([0, 666]);

function draw(data) {
    // make data flat array of numbers to find max value for xScale domain
  var dataValues = data.reduce(
    (result, currentVal) => result.concat([currentVal.in, currentVal.out]), 
    []
  );
  // set x axis domain
  xScale.domain([0, d3.max(dataValues)]);

    var groupsUpdate = groupsSelection.data(data);

  // groups
  var groups = groupsUpdate.enter()
      .append('div')
        .attr('class', 'group')
      .merge(groupsUpdate);

  // derive data from parent group
  var barsUpdate = groups.selectAll('.bar')
    .data(d => [d.in, d.out]);

  var bars = barsUpdate.enter()
    .append('div')
      .attr('class', 'bar')
    .merge(barsUpdate)
      .text(d => d)
        .style('background', 'pink')
      .style('width', d => xScale(d) + 'px');

  barsUpdate.exit().remove();

  // groups exit
  groupsUpdate.exit().remove();
}

// 1st time draw
draw(data)

// delayed data update (2nd draw)
setTimeout(() => {
    var newData = [
    { "in" : 0, "out" : 40 },
    { "in" : 20, "out" : 40 }
  ];
  draw(newData);
}, 1000);

JSFiddle:https://jsfiddle.net/0d7665nc/10/

1 个答案:

答案 0 :(得分:1)

draw功能中,而不是:

var groupsUpdate = groupsSelection.data(data);

应该是:

var groupsUpdate = chart.selectAll('.group').data(data);

或者,移动变量赋值...

var groupsSelection = chart.selectAll('.group');

...到draw内。

这样做的原因是groupsSelection在被追加任何组之前被定义,并且它是一个空的选择。

以下是仅包含此更改的代码:

// .chart -> .group -> .bar
// each group has 2 bars: one for data 'in' and another for 'out'
var data = [{
  "in": 0,
  "out": 40
}, {
  "in": 10,
  "out": 39
}, {
  "in": 20,
  "out": 40
}];

var chart = d3.select('.chart');
var groupsSelection = chart.selectAll('.group');
var xScale = d3.scaleLinear().range([0, 666]);

function draw(data) {
  // make data flat array of numbers to find max value for xScale domain
  var dataValues = data.reduce(
    (result, currentVal) => result.concat([currentVal.in, currentVal.out]), []
  );
  // set x axis domain
  xScale.domain([0, d3.max(dataValues)]);

  var groupsUpdate = chart.selectAll('.group').data(data);

  // groups
  var groups = groupsUpdate.enter()
    .append('div')
    .attr('class', 'group')
    .merge(groupsUpdate);

  // derive data from parent group
  var barsUpdate = groups.selectAll('.bar')
    .data(d => [d.in, d.out]);

  var bars = barsUpdate.enter()
    .append('div')
    .attr('class', 'bar')
    .merge(barsUpdate)
    .text(d => d)
    .style('background', 'pink')
    .style('width', d => xScale(d) + 'px');

  barsUpdate.exit().remove();

  // groups exit
  groupsUpdate.exit().remove();
}

// 1st time draw
draw(data)

// delayed data update (2nd draw)
setTimeout(() => {
  var newData = [{
    "in": 0,
    "out": 40
  }, {
    "in": 20,
    "out": 40
  }];
  draw(newData);
}, 1000);
.chart {
  background: #fff;
  width: 686px;
  padding: 20px;
}

.group {
  background: grey;
  padding: 10px;
  border: solid 1px #000;
  margin: 10px 0;
}

.bar {
  background: white;
  margin: 5px 0;
  height: 20px;
  border: solid 1px yellow;
  font-size: 16px;
  line-height: 20px;
  text-indent: 10px;
  color: white;
  font-weight: bold;
  text-shadow: 0 1px 1px #000;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="chart"></div>