admin管理员组

文章数量:1325955

I'm using the following code to update a bar-chart created with 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);});
        });

Although data is added and rect elements are also created, the transition doesn't happen for the latest added element in the array. It only happens when the next element is added and the transition for that element does not happen.

Can anyone provide any hints as to what might be going wrong??

Thanks in advance..

I'm using the following code to update a bar-chart created with 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);});
        });

Although data is added and rect elements are also created, the transition doesn't happen for the latest added element in the array. It only happens when the next element is added and the transition for that element does not happen.

Can anyone provide any hints as to what might be going wrong??

Thanks in advance..

Share Improve this question edited Oct 20, 2016 at 13:40 Gerardo Furtado 102k9 gold badges128 silver badges177 bronze badges asked Oct 20, 2016 at 11:33 Varun SharmaVarun Sharma 1,7521 gold badge15 silver badges37 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 9

Since this is D3 v4, you'll have to merge the selections.

Every time you push one new value in your data array, your "enter" selection has one element. However, the transition doesn't happen for this new element, because you're calling the transition using bars and, unless you merge the selections, bars doesn't contain the "enter" selection.

So, your "enter" + "update" selections should be:

 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);});

I know that this is "strange", but if you stop to think about it, the old D3 v3 way of dealing with the update selection is the wrong one, not this new v4 way. After all, bars doesn't contain the "enter" selection.

According to Mike Bostock:

D3 2.0 introduced a change to address [...] duplication: appending to the enter selection would now copy entering elements into the update selection. Thus, any operations applied to the update selection after appending to the enter selection would apply to both entering and updating elements, and duplicate code could be eliminated [...] This made usability worse. D3 4.0 removes the magic of enter.append.

(source: https://medium./@mbostock/what-makes-software-good-943557f8a488#.293tkrlfo, emphasis mine)

本文标签: javascriptD3js update with transitionStack Overflow