我正在使用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);
})