D3:如何使用新数据更新分组的栏

时间:2019-01-04 09:19:09

标签: javascript d3.js

我正在使用d3 v4生成分组的条形图。我希望初始图表仅包含我的数据的一个子集,然后单击按钮,添加代表我的其余数据的额外条形。问题是我的当前代码在单击按钮后没有添加这些其他条形。我要去哪里错了?

我已经查看了以下问题的答案:D3: update data in group selection with additional ('g')D3: update data with multiple elements in a group,但这些似乎与d3 v3有关。我还阅读了Scott Murray的“交互式数据可视化”书的第9章。

JS小提琴here

<html>
<input id="AddData" type="button" value="Add Data" onclick="msg()">
<script src="https://d3js.org/d3.v4.min.js"></script>
</html>

Javascript:

//Width and height
var w = 800;
var h = 500;
var padding = 50;

//data
var data = [{
AbsLabel: "A",
AbsA: 5,
AbsB: 10.5
},
{
AbsLabel: "B",
AbsA: 12,
AbsB: 24
},
{
AbsLabel: "C",
AbsA: 11,
AbsB: 22
},
{
AbsLabel: "D",
AbsA: 9,
AbsB: 18
},
];

var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);

 //filter to subset of data
 var NonNans = data.filter(function(d) {
 return "A" == d.AbsLabel
 })

 //set scales
 var xScale0 = d3.scaleBand()
 .domain(NonNans.map(d => d.AbsLabel))
 .range([padding, w])

 var xScale1 = d3.scaleBand()
 .domain(['AbsA', 'AbsB'])
 .range([0, xScale0.bandwidth()]);

 var yScale = d3.scaleLinear()
 .domain([0, d3.max(NonNans, function(d) {
 return Math.max(d.AbsA, d.AbsB)
 })])
 .range([h - padding, padding])

 var xAxis = d3.axisBottom(xScale0)

 var yAxis = d3.axisLeft(yScale)

 //add groups
 var model_name = svg.selectAll(".model_name")
.data(NonNans)
.enter()
.append("g")
.attr("class", "model_name")
.attr("transform", d => `translate(${xScale0(d.AbsLabel)},0)`);

 //add bar 1
var Bar1 = model_name.selectAll(".bar.field1")
.data(NonNans)
.enter()
.append("rect")
.attr("class", "bar field1")
.style("fill", "blue")
.attr("x", d => xScale1('AbsA'))
.attr("y", d => yScale(d.AbsA))
.attr("width", xScale1.bandwidth())
.attr("height", d => {
return yScale(0) - yScale(d.AbsA)
});

//add bar 2
var Bar2 = model_name.selectAll(".bar.field2")
.data(NonNans)
.enter()
.append("rect")
.attr("class", "bar field2")
.style("fill", "red")
.attr("x", d => xScale1('AbsB'))
.attr("y", d => yScale(d.AbsB))
.attr("width", xScale1.bandwidth())
.attr("height", d => {
return yScale(0) - yScale(d.AbsB)
});

// Add  X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");

 //Add Y Axis
 svg.append("g")
 .attr("class", "y axis")
 .attr("transform", "translate(" + padding + ",0)")
 .call(yAxis);

//button
d3.select("#AddData")
.on("click", function() {

//expands data
NonNans = data.filter(function(d) {
  return !isNaN(d.AbsA);
})

//updates scales
xScale0 = d3.scaleBand()
  .domain(NonNans.map(d => d.AbsLabel))
  .range([padding, w])

xScale1 = d3.scaleBand()
  .domain(['AbsA', 'AbsB'])
  .range([0, xScale0.bandwidth()]);

yScale = d3.scaleLinear()
  .domain([0, d3.max(NonNans, function(d) {
    return Math.max(d.AbsA, d.AbsB)
  })])
  .range([h - padding, padding])

xAxis = d3.axisBottom(xScale0)
yAxis = d3.axisLeft(yScale)

//update groups
model_name.data(NonNans)
  .enter()
  .append("g")
  .attr("class", "model_name")
  .merge(model_name)
  .attr("transform", d => `translate(${xScale0(d.AbsLabel)},0)`);

//update bar 1
Bar1.data(NonNans)
  .enter()
  .append("rect")
  .attr("class", "bar field1")
  .style("fill", "blue")
  .merge(Bar1)
  .transition()
  .duration(1000)
  .attr("x", d => xScale1('AbsA'))
  .attr("y", function(d) {
    return yScale(d.AbsA)
  })
  .attr("width", xScale1.bandwidth())
  .attr("height", d => {
    return yScale(0) - yScale(d.AbsA)
  });
//update bar 2
Bar2.data(NonNans)
  .enter()
  .append("rect")
  .attr("class", "bar field2")
  .style("fill", "red")
  .merge(Bar2)
  .transition()
  .duration(1000)
  .attr("x", d => xScale1('AbsB'))
  .attr("y", function(d) {
    return yScale(d.AbsB)
  })
  .attr("width", xScale1.bandwidth())
  .attr("height", d => {
    return yScale(0) - yScale(d.AbsB)
  });

//update axis
svg.select(".x.axis")
  .transition()
  .duration(1000)
  .attr("transform", "translate(0," + (h - padding) + ")")
  .call(xAxis)
  .selectAll("text")
  .style("text-anchor", "end")
  .attr("dx", "-.8em")
  .attr("dy", ".15em")
  .attr("transform", "rotate(-65)");

svg.select(".y.axis")
  .transition()
  .duration(1000)
  .attr("transform", "translate(" + padding + ",0)")
  .call(yAxis);

})

0 个答案:

没有答案