Обновление 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, выделено мое)

Другие вопросы по тегам