Search code examples
javascriptanimationd3.jschartsrestart

Restart D3 bar chart animation


I am working on a widget that shows several D3 bar charts with different values, one after the other, in a sliding carousel.

When the page loads, the bar chart animate as it should, but when the page goes on to the next chart - whether it be on click or by itself - I would like it to restart the animation again each time. I have tried calling animateChart() in the console but this doesn't work.

I am looking for a function that I can call from the console or from another function, like animateChart(), that will reload the D3 bar chart animation.

Here is a link to my widget:

http://jsfiddle.net/alocdk/oa5tg1qu/1/


Solution

  • I've found where you could enhance your animateChart function.

    In fact you were modifying only data that were enterring your graph.

    By calling :

    d3.select(svg)
            .selectAll("rect")
            .data(data)
            .enter().append("rect")
    [...]
    

    Everything following this, will only apply on the new data.

    You may want to read these to understand the pattern to follow with data update in D3.

    Here is my shot now http://jsfiddle.net/uknynmqa/1/

    I've removed the loop you were doing on all your svg, because I assumed you wanted to only animate the current one.

    And your function is updating all of the data, and not only those enterring thanks to :

    // Update the data for all
    var join = d3.select(svg)
        .selectAll("rect")
        .data(data);
    
    // Append new data.
    join.enter().append("rect")      
        .attr("class", function (d, i) {
            var low = ""
            i == minIndex ? low = " low" : "";
            return "bar" + " " + "index_" + i + low;
        })
    
    // Update everyone.
    join.attr("width", barWidth)
        .attr("x", function (d, i) {
            return barWidth * i + barSpace * i;
        })
        .attr("y", chartHeight)
        .attr("height", 0)
        .transition()
        .delay(function (d, i) {
            return i * 100;
        })
        .attr("y", function (d, i) {
            return chartHeight - y(d);
        })
        .attr("height", function (d) {
            return y(d);
        });
    

    D3 is following a really specific data update pattern.

    Depending on what you want to do, you can follow this. It's up to you what you want to animate or not.

    // Link data to your graph and get the join
    var join = svg.selectAll('rect')
        .data(data);
    
    // Update data already there
    join.attr('x', 0);
    
    // Append the new data
    join.enter().append('rect')
        .attr('x', 0);
    
    // Remove exiting elements not linked to any data anymore
    join.exit().remove();
    
    // Update all resulting elements
    join.attr('x', 0);