Interactive Updating

Expanding on the previous post, we will refactor the 3 circles into something a bit more interactive.

https://embed.plnkr.co/4Zok6qR6EoYPEhYINUWv/


Lets take a look at the script:

      var dataList = [4,5,4];
      var svg = d3.select("svg");

      svg.on("click",update);
      
      svg.attr("width" ,"500px")
         .attr("height","200px")
         .style("background-color","lightgrey");
      update();
      
      function update(){
        dataList[0] = Math.random()*10;
        dataList[1] = Math.random()*10;
        dataList[2] = Math.random()*10;
        
        var circles = svg.selectAll("circle").data(dataList);
        
        circles.enter()
             .append("circle")
             .attr("cy","100")
             .attr("cx",function(d,i){return (i+1)*120;})
             .style("fill","blue")
             .merge(circles)   
                 .transition()
                 .attr("r",function(d){return d*10;});
      }

Lets take it line by line
      // Our data array and a reference to our SVG canvas
      var dataList = [4,5,4];

      var svg = d3.select("svg");

      // Something new! The selection.on() method allows us to 
      // bind an event to a method. In this case the click event
      // will trigger a function called update()
      svg.on("click",update);
      
      // Some basic attribute settings for our svg
      svg.attr("width" ,"500px")
         .attr("height","200px")
         .style("background-color","lightgrey");
      
      // Call the update() function the first time to get the
      // ball rolling
      update();
      
      // Our new update function
      function update(){
        // A really clunky way to set our datapoints to 3
        // random numbers. No one ever accused me of being elegant.
        dataList[0] = Math.random()*10;
        dataList[1] = Math.random()*10;
        dataList[2] = Math.random()*10;
        
        // Here we bind the dataList to circle elements under the
        // svg. And we save the existing element list in "circles"
        var circles = svg.selectAll("circle").data(dataList);
        
        // We now change our selection to the enter() list 
        circles.enter()

             // Append new circles for new items (will happen the 
             // first time through the function
             .append("circle")

             // Set the cx, cy and color the first time
             .attr("cy","100")
             .attr("cx",function(d,i){return (i+1)*120;})
             .style("fill","blue")

             // We are working with the enter() set currently, but
             // now we want to effect all new and existing circles
             // so we merge() the circles selection with the enter()
             // selection, making a new set to operate on.
             .merge(circles)   

                 // We add in the transition method to cause the
                 // next attribute setting to interpolate between
                 // values instead of jumping from one setting to 
                 // another. This is to make things look nice!
                 .transition()

                 // Finally set the new radius based on the data
                 // Each time the function is run these values will
                 // change and the circles will adjust to their new 
                 // size.
                 .attr("r",function(d){return d*10;});
      }

Try it out on this plunker

Comments