block by alansmithy e984477a741bc56db5a5

d3js - enter(), update() and exit()

Full Screen

This is a simple example of enter/update/exit in d3js.

2 arrays - of differing length - are used to generate alternating sequences of bubbles.

.enter() creates the initial join of data to elements, creating one circle element for every data element in the array.

After the button is clicked, the alternative array is rejoined to the graphical elements.

Because each array is of a different length, this means we must use .exit() to remove any circle elements no longer needed and create any new circle elements by using .enter().

Once all circle elements are properly defined, we can then update the radius of each circle, new and old, according to its value in the new array.

For more details on enter/update/exit, see this useful article by Mike Bostock, creator of d3js.

index.html

<!doctype html>
<html>
    <head>
        <style>
            svg {width:500px; height:500px}
            button  {float:left}
            line    {stroke:#ddd;shape-rendering: crispEdges;}
            text    {text-anchor:middle;}
            circle {fill:orange;stroke:orange;fill-opacity:0.5;}
            .axis line {fill:none;stroke:#ddd;shape-rendering: crispEdges;}
            .axis path  {fill:none;}
            .axis text {font-size:0.7em;fill:#555;font-family:sans-serif}
        </style>
        <script src="//d3js.org/d3.v3.js"></script>
    </head>
    <body>
        
        <script>
            
            //2 different data arrays
            var dataArray1 = [30,35,45,55,70];
            var dataArray2 = [50,55,45,35,20,25,25,40];
            
            //globals
            var dataIndex=1;
            var xBuffer=50;
            var yBuffer=150;
            var lineLength=400;
            
            
            //create main svg element
            var svgDoc = d3.select("body").append("svg")

            svgDoc.append("text")
                .attr("x",xBuffer+(lineLength/2))
                .attr("y",50)
                .text("dataset"+dataIndex);
            
            //create axis line
            svgDoc.append("line")
                .attr("x1",xBuffer)
                .attr("y1",yBuffer)
                .attr("x1",xBuffer+lineLength)
                .attr("y2",yBuffer)
            
            //create basic circles
            svgDoc.append("g").selectAll("circle")
                .data(eval("dataArray"+dataIndex))
                .enter()
                .append("circle")
                .attr("cx",function(d,i){
                    var spacing = lineLength/(eval("dataArray"+dataIndex).length);
                    return xBuffer+(i*spacing)
                })
                .attr("cy",yBuffer)
                .attr("r",function(d,i){return d});
            
            //button to swap over datasets
            d3.select("body").append("button")
                .text("change data")
                .on("click",function(){
                    //select new data
                    if (dataIndex==1) {
                        dataIndex=2;  
                    } else   {
                        dataIndex=1;
                    }
                    //rejoin data
                    var circle = svgDoc.select("g").selectAll("circle")
                        .data(eval("dataArray"+dataIndex));
                    
                    circle.exit().remove();//remove unneeded circles
                    circle.enter().append("circle")
                        .attr("r",0);//create any new circles needed

                    //update all circles to new positions
                    circle.transition()
                        .duration(500)
                        .attr("cx",function(d,i){
                            var spacing = lineLength/(eval("dataArray"+dataIndex).length);
                            return xBuffer+(i*spacing)
                        })
                        .attr("cy",yBuffer)
                        .attr("r",function(d,i){return d});

                    d3.select("text").text("dataset"+dataIndex);

                });//end click function

            
        </script>
    </body>
</html>