我修改了一些d3过滤块,意图按年过滤(理想情况下是通过滑块而不是每年都有一个按钮),但遇到了两个问题:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<meta charset="utf-8">
<title>D3: Loading data from a CSV file</title>
</head>
<body>
<p class="s12"> select 2012 </p>
<p class="s16"> select 2016 </p>
<script type="text/javascript">
var margin = {top: 20, right: 20, bottom: 30, left: 40},
w = 600 - margin.left - margin.right,
h = 300 - margin.top - margin.bottom;
var padding = 40;
var data = [{
"Food": "Apples",
"Deliciousness": 9,
"year": 2010
}, {
"Food": "Green Beans",
"Deliciousness": 5,
"year": 2012
}, {
"Food": "Egg Salad Sandwich",
"Deliciousness": 4,
"year": 2016
}, {
"Food": "Cookies",
"Deliciousness": 10,
"year": 2018
} ];
// format the data
data.forEach(function(d) {
d.Deliciousness = +d.Deliciousness;
});
var svg = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left+"," +
margin.top+")");
var xScale = d3.scaleBand()
.domain(d=>d.Food)
.range([margin.left,w+margin.left])
.paddingInner(0.2);
xScale.domain(data.map(function(d) { return d.Food; }));
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(5);
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, d=>d.Deliciousness)])
.rangeRound([h+margin.top,margin.top]);
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(5);
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x',(d,i) => margin.left + i*w/data.length)
.attr('y',d=>yScale(d.Deliciousness))
.attr('width', xScale.bandwidth())
.attr('height',d =>h-yScale(d.Deliciousness))
.attr('fill',function(d){
if (d===30) return "red";
return "rgb(0,0,"+d.Deliciousness*10+")" ;});
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
d3.select(".s12")
.on("click", function() {
svg.selectAll("rect")
.filter(function(d) {
return d.year !== 2012;
})
.remove();
d3.select(".s16")
.on("click", function() {
svg.selectAll("rect")
.filter(function(d) {
return d.year !== 2016;
})
.remove();
});
</script>
</body>
</html>
代码已更新
答案 0 :(得分:1)
首先,修复comments section中解释的类问题。
这里你的问题是这个块的逻辑:
svg.selectAll("rect")
.data(data.filter(function(d) {
return d.year == 2012;
}))
.exit().remove();
这没有多大意义:你正在做的是按年(2012)过滤数据数组,这将只返回 1 对象。然后,您选择所有矩形,仅使用一个对象绑定一个新数据数组(这将保留所有其他矩形,没有任何数据),然后在退出选择上调用remove
。那不对。
由于您没有新数据,只需过滤选择:
svg.selectAll("rect")
.filter(function(d) {
return d.year !== 2012;
})
.remove();
这样,您只需删除不代表2012的矩形。
这是更新的代码:
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
w = 600 - margin.left - margin.right,
h = 300 - margin.top - margin.bottom;
var padding = 40;
var data = [{
"Food": "Apples",
"Deliciousness": 9,
"year": 2010
}, {
"Food": "Green Beans",
"Deliciousness": 5,
"year": 2012
}, {
"Food": "Egg Salad Sandwich",
"Deliciousness": 4,
"year": 2016
}, {
"Food": "Cookies",
"Deliciousness": 10,
"year": 2018
}];
// format the data
data.forEach(function(d) {
d.Deliciousness = +d.Deliciousness;
});
var svg = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," +
margin.top + ")");
var xScale = d3.scaleBand()
.domain(d => d.Food)
.range([margin.left, w + margin.left])
.paddingInner(0.2);
xScale.domain(data.map(function(d) {
return d.Food;
}));
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(5);
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.Deliciousness)])
.rangeRound([h + margin.top, margin.top]);
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(5);
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', (d, i) => margin.left + i * w / data.length)
.attr('y', d => yScale(d.Deliciousness))
.attr('width', xScale.bandwidth())
.attr('height', d => h - yScale(d.Deliciousness))
.attr('fill', function(d) {
if (d === 30) return "red";
return "rgb(0,0," + d.Deliciousness * 10 + ")";
});
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
d3.select(".s12")
.on("click", function() {
svg.selectAll("rect")
.filter(function(d) {
return d.year !== 2012;
})
.remove();
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<p class="s12"> select 2012 </p>
<p class="s16"> select 2016 </p>