Making an interactive line graph with D3.js

Along with the interactive histogram for the MPG tracking page I also added some interactivity to the miles over time graph. Below is the code and data that produces the above plot. The code for this example and the entire MPG project is available on github.

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <body>
    <title>MPG Data</title>
    <style>
      .d3-tip {
        line-height: 1;
        font-weight: bold;
        padding: 12px;
        background: rgba(0, 0, 0, 0.8);
        color: #fff;
        border-radius: 2px;
      }
      path {
        stroke: steelblue;
        stroke-width: 3;
        fill: none;
      }
      .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
      }
      .datapoint:hover{
	fill: steelblue;
      }
      .xlabel, .ylabel {
        font-weight:bold;
	font-size:20px;
      }
    </style>

    <script src="../../mpg/lib/d3.v3.min.js"></script>
    <!See https://github.com/Caged/d3-tip  (d3.tip.js is the index.js file)>
    <script src="../../mpg/lib/d3.tip.v0.6.3.js"></script>
<script>
// plot a graph of miles vs. time

function parser(d) {
    d.pMPG = +d.MPG;
    d.pOdometer = +d.Odometer;
    d.pDate = new Date(d.Date);
    return d;
}

var format = d3.time.format("%m/%d/%Y");

function milesovertime(csvdata) {
    var margin = {top: 30, right: 30, bottom: 75, left: 100};
    var width = 500 - margin.left - margin.right;
    var height = 400 - margin.top - margin.bottom;

    var minDate = csvdata[0].pDate;
    var maxDate = csvdata[csvdata.length - 1].pDate;
	console.log(maxDate);
    // Set up time based x axis
    var x = d3.time.scale()
	  .domain([minDate, maxDate])
	  .range([0, width]);

    var y = d3.scale.linear()
	  .domain([0, 10000])
	  .range([height, 0]);

    var xAxis = d3.svg.axis()
	  .scale(x)
	  .ticks(10)
	  .orient("bottom");

    var yAxis = d3.svg.axis()
	  .scale(y)
	  .ticks(7)
	  .orient("left");

    // put the graph in the "miles" div
    var svg = d3.select("#miles").append("svg")
	  .attr("width", width + margin.left + margin.right)
	  .attr("height", height + margin.top + margin.bottom)
	  .append("g")
	  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // function to draw the line
    var line = d3.svg.line()
	.x(function(d) { return x(d.pDate); } )
	.y(function(d) { return y(d.pOdometer); } );

    //Mouseover tip
    var tip = d3.tip()
	.attr('class', 'd3-tip')
	.offset([120, 40])
	.html(function(d) {
	    return "<strong>" + d.Odometer +
                " miles</strong><br>" +
		d.MPG + " mpg" + "<br>" +
		format(d.pDate) + "<br>" + 
		d.Brand + ", " + d.City +
                " " + d.State + "<br>";
	});

    svg.call(tip);

    // add the x axis and x-label
    svg.append("g")
	  .attr("class", "x axis")
	  .attr("transform", "translate(0," + height + ")")
	  .call(xAxis)
	  .selectAll("text")
	  .attr("y", 9)
	  .attr("x", 9)
	  .attr("dy", ".35em")
	  .attr("transform", "rotate(45)")
	  .style("text-anchor", "start");
    svg.append("text")
	  .attr("class", "xlabel")
	  .attr("text-anchor", "middle")
	  .attr("x", width / 2)
	  .attr("y", height + margin.bottom)
	  .text("Month in 2013");

    // add the y axis and y-label
    svg.append("g")
	  .attr("class", "y axis")
	  .attr("transform", "translate(0,0)")
	  .call(yAxis);
    svg.append("text")
	  .attr("class", "ylabel")
	  .attr("y", 0 - margin.left) // x and y switched due to rotation!!
	  .attr("x", 0 - (height / 2))
	  .attr("dy", "1em")
	  .attr("transform", "rotate(-90)")
	  .style("text-anchor", "middle")
	  .text("Odometer reading (mi)");

    svg.append("text")
	  .attr("class", "graphtitle")
	  .attr("y", 10)
	  .attr("x", width/2)
	  .style("text-anchor", "middle")
	  .text("MILES OVER TIME");

    // draw the line
    svg.append("path")
	  .attr("d", line(csvdata));

    svg.selectAll(".dot")
	  .data(csvdata)
	  .enter().append("circle")
	  .attr('class', 'datapoint')
	  .attr('cx', function(d) { return x(d.pDate); })
	  .attr('cy', function(d) { return y(d.pOdometer); })
	  .attr('r', 6)
	  .attr('fill', 'white')
	  .attr('stroke', 'steelblue')
	  .attr('stroke-width', '3')
	  .on('mouseover', tip.show)
	  .on('mouseout', tip.hide);
}
// Read in .csv data and make graph
d3.csv("prius_gas.csv", parser,
       function(error, csvdata) {
	   milesovertime(csvdata);
}); 
	
</script>
    <div id="miles" class="graph"></div>
  </body>
</html>

prius_gas.csv

Date,Brand,City,State,Odometer,MPG
2/22/2013,Texaco,Mariposa,CA,245,NA
2/24/2013,Chevron,Berkeley,CA,707,48.75
3/8/2013,Chevron,Tahoe City,CA,1028,39.45
3/12/2013,Chevron,Meyers,CA,1430,47.05
4/8/2013,Chevron,San Rafael,CA,1871,53.09
4/26/2013,Chevron,Berkeley,CA,2088,45.55
4/27/2013,Chevron,Tehachapi,CA,2434,51.8
4/28/2013,Chevron,Hurricane,UT,2812,52.54
5/1/2013,Chevron,Bryce,UT,2934,DNF
5/4/2013,Texaco,Scipio,UT,3292,49
5/4/2013,Chevron,Ely,NV,3501,48.45
5/5/2013,Chevron,Colfax,CA,3910,52.18
5/24/2013,Chevron,Vacaville,CA,4197,50.7
5/25/2013,Chevron,Roseburg,OR,4582,46.54
5/27/2013,Texaco,Crescent City,CA,4954,47.59
5/29/2013,Chevron,Berkeley,CA,5350,44.03
6/5/2013,Chevron,Berkeley,CA,5716,52.81
6/14/2013,Chevron,Berkeley,CA,6191,57.61
6/22/2013,Chevron,Berkeley,CA,6721,56.61
7/1/2013,Chevron,Berkeley,CA,7162,55.11
7/9/2013,Chevron,Berkeley,CA,7606,55.36
7/13/2013,Chevron,Berkeley,CA,7937,56.8
7/20/2013,Chevron,Berkeley,CA,8364,55.93
7/29/2013,Chevron,Berkeley,CA,8897,55.73
8/4/2013,Chevron,Berkeley,CA,9191,56.17
8/20/2013,Chevron,Berkeley,CA,9678,53.69
8/23/2013,Texaco,Mariposa,CA,9871,52.96

D3-tip project: http://labratrevenge.com/d3-tip/