Tuesday, January 3, 2012

Using D3.js to draw a grid

Using D3.js to draw a grid In a previous post, entitled "Drawing a straight line with D3.js, you saw how to draw a single line. In this post, we will draw a grid, which requires us to draw multiple lines. We will see two ways of doing this:
  1. The first way uses the standard for loop of JavaScript to achieve this (in addition to the technique we discussed in the previous post). It does not use any feature specific to D3.js that we did not talk about in the previous post.
  2. The second way illustrates use of D3.js methods that make it possible to bind given data to graphical elements. In other words, it illustrates use of D3.js methods that add graphical elements automatically based on available data. When you are creating graphics to represent data that you already have, this approach will be more useful.

  1. Drawing a grid using for loops and D3.js
  2. The following code illustrates how to draw a grid using for loops. Create a DIV container in your HTML file, <div id="D3lines"></div> and add the following javascript code:
     // Select the DIV container "D3line" then
     // add an SVG element to it
    
     var width = 400;
     var height = 400;
     
     var lineGraph = d3.select("#D3lines")
         .append("svg:svg")
         .attr("width", width)    
         .attr("height", height); 
     
     // To draw a line use the "svg:line" element.
     // "svg:line" element requires 4 attributes (x1, y1, x2, and y2)
     // (x1,y1) are coordinates of the starting point. 
     // (x2,y2) are coordinates of the end point.
     // You also need to specify the stroke color.
    
     // Using for loop to draw multiple horizontal lines
     for (var j=25; j <= width-25; j=j+25) {
         lineGraph.append("svg:line")
             .attr("x1", 25)
             .attr("y1", j)
             .attr("x2", width-25)
             .attr("y2", j)
             .style("stroke", "rgb(6,120,155)")
             .style("stroke-width", 2);            
     };
     
     // Using for loop to draw multiple vertical lines
     for (var j=25; j <= height-25; j=j+25) {
         lineGraph.append("svg:line")
             .attr("x1", j)
             .attr("y1", 25)
             .attr("x2", j)
             .attr("y2", height-25)
             .style("stroke", "rgb(6,120,155)")
             .style("stroke-width", 2);            
     };
    
    This script gives:

    Note that in the for loops, the values of the line attributes (x1, y1, x2, y2) are specified when the lines are being generated.



  3. Drawing a grid using given coordinate data to generate the line elements.
  4. The following code illustrates how to use data that has already been created, to generate line elements. Create a DIV container <div id="D3grid_D3way"></div> and add the following script to your HTML file.
     // Select the DIV container "D3grid_D3way", then
     // add an SVG element to it
        
     var width = 400;
     var height = 400;
     
     var gridGraph = d3.select("#D3grid_D3way")
         .append("svg:svg")
         .attr("width", width)     // Set width of the SVG canvas
         .attr("height", height);   // Set height of the SVG canvas
     
     
     // the yaxiscoorddata gives the y coordinates
     // for horizontal lines ("x1" = 25 and, "x2"=width-25)
     var yaxiscoorddata = d3.range(25, height, 25);
     
     // the xaxiscoorddata gives the x coordinates
     // for vertical lines ("y1" = 25 and, "y2"=height-25)
     var xaxiscoorddata = d3.range(25, width, 25);
     
     
     // Using the xaxiscoorddata to generate vertical lines.
     gridGraph.selectAll("line.vertical")
     .data(xaxiscoorddata)
     .enter().append("svg:line")
     .attr("x1", function(d){return d;})
     .attr("y1", 25)
     .attr("x2", function(d){return d;})
     .attr("y2", height-25)
     .style("stroke", "rgb(6,120,155)")
     .style("stroke-width", 2);       
     
     
     // Using the yaxiscoorddata to generate horizontal lines.       
     gridGraph.selectAll("line.horizontal")
     .data(yaxiscoorddata)
     .enter().append("svg:line")
     .attr("x1", 25)
     .attr("y1", function(d){return d;})
     .attr("x2", width-25)
     .attr("y2", function(d){return d;})
     .style("stroke", "rgb(6,120,155)")
     .style("stroke-width", 2);
    
    This script gives the same grid as above.

    Function d3.range(start, stop, step) generates an array of numbers from start to stop (excluding stop) with the difference between the two successive numbers given by step. For example: d3.range(0,25,5) returns [0, 5, 10, 15, 20].

    To understand the magic from line gridGraph.selectAll("line.vertical") onwards, I suggest you see my other post on Understanding selectAll, data, enter, append sequence in D3.js. You can also see Jerome Cukier's post on understanding selections. Jerome gives a good explanation of how data is used to create graphical elements with an example in which he creates bar charts. Go to the post and scroll down to the section entitled, "Bonus: understanding selections".

2 comments: