Animated List (D3 w/DOM)

by Ryan

HTML

<script src="https://d3js.org/d3.v3.min.js"></script>
<button id="update">Update</button>
<div id="container"></div>

CSS

#container {
    position: relative;
}
.list-item {
    border: black 1px solid;
    padding: 2px;
    margin: 2px;
    width: 100px;
    position: absolute;
    left: 0px;
    height: 20px;
}
.enter {
    border-color: green;
}
.exit {
    border-color: red;
}

JavaScript

var rawData = [ 
    { name: "a", score: 0 }, 
    { name: "b", score: 1 }, 
    { name: "c", score: 2 }, 
    { name: "d", score: 3 }, 
    { name: "e", score: 4 }, 
    { name: "f", score: 5 }, 
    { name: "g", score: 6 }, 
    { name: "h", score: 7 }, 
    { name: "i", score: 8 }, 
    { name: "j", score: 9 }
];

var container = d3.select("#container");
var boxHeight = 30;
var redraw = function(data){
    console.log("data", data);
    
    // Join
    var div = container.selectAll("div.list-item")
        .data(data, function(d) { return d.name; } );
    console.log("joined data", data);
    
    // Update
    div.attr("class", "list-item")
        .transition().duration(500)
        .style("left", "0px")
        .style("opacity", 1)
        .style("top", function(d, i) { return (boxHeight * i) + "px"; } );
    
    // Enter
    div.enter().append("div")
        .attr("class", "list-item enter")
        .style("opacity", 0)
        .style("top", function(d, i) { return (boxHeight * i) + "px"; } )
        .style("left", "-100px")
        .text(function(d) { return d.name + " : " +  d.score; })
        .transition().duration(500)
            .style("opacity", 1)
            .style("left", "0px");

    //Exit
    div.exit()
        .attr("class", "list-item exit")
        .transition().duration(500)
            .style("opacity", 0)
            .style("left", "100px")
            .remove();
    
};

var update = function(){
    var newData = [];
    rawData.forEach(function(d){
        if(0 !== Math.floor(Math.random() * 5)){
            newData.push(d);
        }
    });
    redraw(newData);
};

redraw(rawData);

d3.select("button#update")
    .on("click", function(d,i) { update(); })