[英]Last element added to a D3 bar chart doesn't sort
我是 D3 / Javascript 菜鳥,我正在嘗試創建一個圖表,其中包含添加條的選項(通過更新 > 輸入選擇),然后對它們進行重新排序。
但是,最后添加的酒吧拒絕參與重新排序。
誰能告訴我:a)為什么會發生這種情況 b)如何解決它
請參閱 Codepen: https ://codepen.io/benjamesdavis/pen/JjodJwy ? editors = 1010
//Width and height
var w = 900;
var h = 450;
var array = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
dataset=[];
for(let i=0; i<array.length; i++)
{dataset[i] = {"key":i, "value": array[i]}}
var xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.rangeRound([0, w])
.paddingInner(0.05);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d=> d.value)])
.range([0, h]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create bars
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
});
//On click, update with new data
d3.select("#newBar")
.on("click", function() {
//Add one new value to dataset
var maxValue = 25;
var newNumber = Math.floor(Math.random() * maxValue);
newNumber = {"key":dataset.length, "value": newNumber}
dataset.push(newNumber);
//Update scale domains
xScale.domain(d3.range(dataset.length));
yScale.domain([0, d3.max(dataset, d=> d.value)]);
//Select…
bars = svg.selectAll("rect")
.data(dataset)
//Enter…
bars.enter()
.append("rect")
.attr("x", w)
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d,i) {
return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
})
.merge(bars)
.transition()
.duration(500)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
});
});
//Re-Sort Bars
d3.select("#sortBars").on("click",function(){
d3.shuffle(dataset)
bars.data(dataset,d => d.key)
.transition(2000)
.attr("x", function(d, i) {
return xScale(i);
})
})
具體問題是,當您enter()
第 70 行的bars
選擇並將其合並到bars
83 行的bars
時,您並沒有將新的合並選擇保存回bars
。 因此,當您在第 104 行重新排序時, bars
更新選擇不包含最新的條形。
通常,要記住的是,數據綁定選擇始終是更新選擇,並且選擇(從 D3v4 開始)是不可變的,因此當您這樣做時
bars.enter()
.<do stuff to just the enter selection>
.merge(bars) // merge the update and enter selections together
.<do more stuff to the merged update+enter selections>
bars
的值仍然是舊的更新選擇。 如果您以后想用它做更多的事情,您必須明確保存合並的選擇。
bars = bars.enter() // note the assignment to bars!
.<do stuff to just the enter selection>
.merge(bars) // merge the update and enter selections together
.<do more stuff to the merged update+enter selections>
我認為是這樣的,當你定義bars時,它是在add-bars函數的范圍內,而不是re-sort函數,所以首先你需要每次都做select。 然后,您需要確保兩次都使用該密鑰。 這是我對您的代碼的看法:
//寬度和高度 var w = 500; 無功h = 200;
var array = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
dataset=[];
for(let i=0; i<array.length; i++)
{dataset[i] = {"key":i, "value": array[i]}}
var xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.rangeRound([0, w])
.paddingInner(0.05);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d=> d.value)])
.range([0, h]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create bars
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
});
//On click, update with new data
d3.select("#newBar")
.on("click", function() {
//Add one new value to dataset
var maxValue = 25;
var newNumber = Math.floor(Math.random() * maxValue);
newNumber = {"key":dataset.length, "value": newNumber}
dataset.push(newNumber);
//Update scale domains
xScale.domain(d3.range(dataset.length));
yScale.domain([0, d3.max(dataset, d=> d.value)]);
//Select…
bars = svg.selectAll("rect")
.data(dataset,d => d.key) //make sure you use the key here too!
//Enter…
bars.enter()
.append("rect")
.attr("x", w)
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d,i) {
return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
})
.merge(bars)
.transition()
.duration(500)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
});
});
//Re-Sort Bars
d3.select("#sortBars").on("click",function(){
d3.shuffle(dataset)
bars = svg.selectAll("rect").data(dataset,d => d.key) //redefine bars, and use the key
.transition(2000)
.attr("x", function(d, i) {
return xScale(i);
})
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.