我是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);
})
})
答案 0 :(得分:1)
我认为这是事实,当您定义钢筋时,它在add-bars函数的范围内,而不是re-sort函数,因此,首先,您需要每次进行选择。然后,您需要确保两次都使用密钥。这是我对您的代码的看法:
//宽度和高度 var w = 500; var 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);
})
})
答案 1 :(得分:1)
具体的问题是,当您在第70行上bars
bars
选择并将其合并到83上的bars
时,您并没有将新的合并选择保存回{ {1}}。结果,当您在第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>