Sunday 22 December 2013

D3 - Simple Line Chart

There seem to be a lot of tutorials on the web about D3 (www.d3js.org). However I've yet to find one that explains,simply, how to create a line chart. They all seem to be overly complicated, don't explain exactly what is happening, or call functions, classes and variables by the same name.

So here's my attempt. It took me a good few hours to get this working, which is pretty poor given that what I achieved is extremely simple.



First Steps

We need to create a html document and reference the various libraries.

<!DOCTYPE html>
<html>
   <head>
<title>Line Chart with D3</title>
<script src="d3.v3.min.js"></script>
   </head>
  <body>

   </body>
</html>

Put the d3 script file in the same directory as the html. Now we create a <div> to hold the script and the script itself. These are placed in the body of the html.

<div id="line_svg">
   <script type="text/javascript">

   </script>
</div>


This allows us to position and style the created SVG separately from the other parts of the html.

Data

Now we need some data to plot. I've just created some random data:

var line_data = [];
line_data.push({"x": 1, "y1": 792});
line_data.push({"x": 2, "y1": 908});
line_data.push({"x": 3, "y1": 1119});
line_data.push({"x": 4, "y1": 1849});
line_data.push({"x": 5, "y1": 1126});
line_data.push({"x": 6, "y1": 825});
line_data.push({"x": 7, "y1": 6613});
line_data.push({"x": 8, "y1": 2127});
line_data.push({"x": 9, "y1": 1302});
line_data.push({"x": 10, "y1": 1365});
line_data.push({"x": 11, "y1": 2235});
line_data.push({"x": 12, "y1": 1123});
line_data.push({"x": 13, "y1": 798});
line_data.push({"x": 14, "y1": 934});


Next Steps

Now we use d3 to create the SVG.

 var chk2 = d3.select("#line_svg")
.append("svg")
.attr("class", "chk")
.attr("width", 800)
.attr("height", 500);

This creates the SVG object with a width and height of 800 and 500 respectively.

We also need to create some scales:

x_scale = d3.scale.linear().domain([1,14]).range([0, 800]);
y_scale = d3.scale.linear().domain([500,7000]).range([500, 0]);

These convert the x data range from 1-14 to 0-800 and the y data range from 500-7000 to 500-0. Zero coordinates for the y-axis start at the top of the SVG object. Hence 7000 gets converted to 0.

Final Steps

Now there are only 2 more steps left. We need to create a d3 line object. This is a helper object that creates the path elements.

    var line1 = d3.svg.line()
    .x(function(d) { return x(d.x); })
    .y(function(d) { return y(d.y1); });

This object is referenced by the next step which creates the path object.

    chk2.append("path")
      .data(line_data)
    .attr("d", line1(line_data));

A path is created using the data specified earlier. This data is passed to the path object directly using the data function and indirectly via the line1 object, which converts the coordinates.

Full Listing


<!DOCTYPE html>
<html>
  <head>
    <title>Line chart with D3</title>
    <script src="d3.v3.min.js"></script>
  </head>
    <body>
        
        <div id="line_svg">
            <script type="text/javascript">
                
                var line_data = [];
                line_data.push({"x": 1, "y1": 792, "y2": 995});
                line_data.push({"x": 2, "y1": 908, "y2": 2021});
                line_data.push({"x": 3, "y1": 1119, "y2": 4649});
                line_data.push({"x": 4, "y1": 1849, "y2": 2717});
                line_data.push({"x": 5, "y1": 1126, "y2": 1706});
                line_data.push({"x": 6, "y1": 825, "y2": 1449});
                line_data.push({"x": 7, "y1": 6613, "y2": 1513});
                line_data.push({"x": 8, "y1": 2127, "y2": 1295});
                line_data.push({"x": 9, "y1": 1302, "y2": 2285});
                line_data.push({"x": 10, "y1": 1365, "y2": 4993});
                line_data.push({"x": 11, "y1": 2235, "y2": 2019});
                line_data.push({"x": 12, "y1": 1123, "y2": 1459});
                line_data.push({"x": 13, "y1": 798, "y2": 1278});
                line_data.push({"x": 14, "y1": 934, "y2": 1348});
                
                var chk2 = d3.select("#line_svg")
                    .append("svg")
                    .attr("class", "chk")
                    .attr("width", 800)
                    .attr("height", 500);
                    
                x = d3.scale.linear().domain([1,14]).range([0, 800]);
                y = d3.scale.linear().domain([500,7000]).range([500, 0]);
                
                var line1 = d3.svg.line()
                    .x(function(d) { return x(d.x); })
                    .y(function(d) { return y(d.y1); });
                    
                chk2.append("path")
                    .data(line_data)
                    .attr("d", line1(line_data))
                    .attr("fill", "none")
                    .attr("stroke", "steelblue")
                    .attr("stroke-width", 1.5);
                
            </script>
        </div>
    </body>
</html>

I've added a few lines to the path so that it displays nicely. But it's still very simple. Obviously more lines can be added and I'll probably develop this further.

No comments:

Post a Comment