在 D3.js 中对条形进行排序不会更改条形图位置



我有一个在 d3 中对柱进行排序的脚本,但不知何故,柱线没有移动。任何人都可以告诉我缺少什么?

<!DOCTYPE html>
<meta charset='utf-8'>
<head>
<title>Simple Bar Chart</title>
</head>
<body>
<div id="buttons">
<p>Sort by</p>
<div class="button current" data-val="A">value</div>
<div class="button" data-val="B">week</div>
<div class="clr"></div>
</div>
<div class='container'>
<div id='viz'></div>
</div>
<script src='https://d3js.org/d3.v4.min.js'></script>
<script>
var sdata = d3.range(10).map(function (d) {
return {
id: d,
week: 1 + Math.floor(Math.random() * 9),
value: Math.floor(Math.random() * 20)
};
});

// Setting the margin and dimensions of the work area
var margin = {
top: 50,
right: 20,
bottom: 30,
left: 30
},
width = 760 - margin.left - margin.right,
height = 280 - margin.top - margin.bottom;
// Creating the scale variables and setting the ranges
var xScale = d3.scaleBand().rangeRound([0, width]).padding(0.1),
yScale = d3.scaleLinear().rangeRound([height, 0]);
// Adjusting data by assigning domain to the range of the scale
var xscale = d3.scaleBand()
.domain(sdata.map(function (d) {
return d.week;
}))
.range([margin.left, width])
.padding(0.1);
// Appending the svg object to the div on the page
var svg = d3.select('#viz').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
// Appending the 'group' element to the svg
// Moving the 'group' element to the top left margin
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

// Creating chart
g.selectAll('bar')
.data(sdata)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function (d, i) {
return 50 * i
})
.attr('height', function (d) {
return height - d.value;
})
.attr('y', function (d) {
return d.value;
})
.attr('width', 30);

g.selectAll(".bar-label")
.data(sdata)
.enter()
.append("text")
.classed("bar-label", true)
.attr("transform", function (d, i) {
return "translate(" + (i * 50) + "," + (height + 15) + ")" +
" rotate(45)"
})
.attr("text-anchor", "left")
.text(function (d) {
return 'wk' + d.week
})
g.selectAll(".bar-label2")
.data(sdata)
.enter()
.append("text")
.classed("bar-label", true)
.attr("transform", function (d, i) {
return "translate(" + (i * 50) + "," + (height - 15) + ")" +
" rotate(45)"
})
.attr("text-anchor", "left")
.text(function (d) {
return 'id: ' + d.id
})
//update 
d3.selectAll(".button").on("click", function () {
selected = d3.select(this).attr("data-val");
console.log(selected)
update(sdata, selected)
})
function update(data, selected) {
data
.sort((a, b) =>
selected === "A" ?
d3.descending(a.value, b.value) :
d3.descending(a.week, b.week)
);
console.log(data)
d3.selectAll('bar')
.transition()
.attr('x', function (d, i) {
return 50 * i
})
}
</script>
</body>

问题是,当您对数组进行排序时,您不会更改连接到 d3 bar 对象的数据。请注意,在您的示例中.data()使用key参数很重要(默认情况下 d3 使用数组索引作为键(。您需要执行以下操作:

首先,更改图表创建代码中的键映射(并将bar选择器替换为.bar选择器(:

// Creating chart
g.selectAll('bar').data(sdata)

// Creating chart
g.selectAll('.bar').data(sdata, function(d){return d.id})

其次,将数据映射添加到更新函数中(并将bar选择器替换为.bar选择器(:

d3.selectAll('bar')
.transition()

d3.selectAll('.bar').data(data, function(d){return d.id})
.transition()

最新更新