Обновление D3.js с переходом
Я использую следующий код для обновления гистограммы, созданной с помощью d3v4:
d3.select("button.add")
.on("click", function(){
dataset.push(Math.floor(Math.random() * 30) + 5);
xScale.domain(d3.range(dataset.length))
.rangeRound([0, w])
.padding(0.2);
yScale.domain([0, d3.max(dataset)]);
var bars = svg.selectAll("rect")
.data(dataset);
bars.enter()
.append("rect")
.attr("class", "bar")
.attr("x", w)
.attr("y", function(d){return yScale(d);})
.attr("width", xScale.bandwidth())
.attr("height", function(d){return h - yScale(d)})
.attr("fill", function(d){
return 'rgb('+d*3 + ',' + d*6 + ',' + d*9 + ')';
});
bars.transition()
.delay(function(d, i){
return(i*1500) / dataset.length;
})
.duration(500)
.ease(d3.easeLinear)
.attr("x", function(d, i){ return xScale(i);})
.attr("y", function(d) {return yScale(d);})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {return h - yScale(d);});
});
Хотя данные добавляются и прямоугольные элементы также создаются, переход не происходит для последнего добавленного элемента в массиве. Это происходит только тогда, когда следующий элемент добавлен и переход для этого элемента не происходит.
Кто-нибудь может дать какие-нибудь подсказки относительно того, что может пойти не так??
Заранее спасибо..
1 ответ
Так как это D3 v4, вам придется merge
выборы.
Каждый раз, когда вы добавляете одно новое значение в массив данных, ваш выбор ввода имеет один элемент. Тем не менее, переход не происходит для этого нового элемента, потому что вы вызываете переход с помощью bars
и, если вы merge
выборы, bars
не содержит выбора "ввод".
Итак, ваш выбор "enter" + "update" должен быть:
bars.enter()// <-- this is just the "enter" selection
.append("rect")
.attr("class", "bar")
.attr("x", w)
.attr("y", function(d){return yScale(d);})
.attr("width", xScale.bandwidth())
.attr("height", function(d){return h - yScale(d)})
.attr("fill", function(d){
return 'rgb('+d*3 + ',' + d*6 + ',' + d*9 + ')';
})
.merge(bars)// <-- merge the selections: from now on, "enter" + "update"
.transition()
.delay(function(d, i){
return(i*1500) / dataset.length;
})
.duration(500)
.ease(d3.easeLinear)
.attr("x", function(d, i){ return xScale(i);})
.attr("y", function(d) {return yScale(d);})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {return h - yScale(d);});
Я знаю, что это "странно", но если вы перестанете думать об этом, старый D3 v3 способ выбора обновлений будет неправильным, а не этот новый способ v4. В конце концов, bars
не содержит выбора "ввод".
По словам Майка Бостока:
D3 2.0 ввел изменение адреса [...] дублирования: добавление к выборке ввода теперь будет копировать вводимые элементы в выборку обновления. Таким образом, любые операции, применяемые к выбору обновлений после добавления к выбору ввода, будут применяться как к элементам ввода, так и к элементам обновления, и дублирующий код может быть исключен [...]. Это ухудшило удобство использования. D3 4.0 удаляет магию enter.append.
(источник: https://medium.com/@mbostock/what-makes-software-good-943557f8a488, выделено мое)