Want to do a line chart with d3? There are no ready APIs right? At least none that I could find. What I did find was http://benjchristensen.com/2012/05/02/line-graphs-using-d3-js/ (very useful!) and I hacked up a line chart taking cue from there.

Here’s an example:

And the code?


	<!DOCTYPE html>
	<html lang="en">
	 <head>
	 <title>Line Charts</title>
	 <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
	 <script src="http://d3js.org/d3.v2.js"></script>
	 <script type="text/javascript">
	 function getDate(d) {
	 var dt = new Date(d.date);
	 dt.setHours(0);
	 dt.setMinutes(0);
	 dt.setSeconds(0);
	 dt.setMilliseconds(0);
	 return dt;
	 }

	function showData(obj, d) {
	 var coord = d3.mouse(obj);
	 var infobox = d3.select(".infobox");
	 // now we just position the infobox roughly where our mouse is
	 infobox.style("left", (coord[0] + 100) + "px" );
	 infobox.style("top", (coord[1] - 175) + "px");
	 $(".infobox").html(d);
	 $(".infobox").show();
	 }

	function hideData() {
	 $(".infobox").hide();
	 }

	var drawChart = function(data) {
	 // define dimensions of graph
	 var m = [20, 40, 20, 100]; // margins
	 var w = 700 - m[1] - m[3]; // width
	 var h = 360 - m[0] - m[2]; // height

	data.sort(function(a, b) {
	 var d1 = getDate(a);
	 var d2 = getDate(b);
	 if (d1 == d2) return 0;
	 if (d1 > d2) return 1;
	 return -1;
	 });

	// get max and min dates - this assumes data is sorted
	 var minDate = getDate(data[0]),
	 maxDate = getDate(data[data.length-1]);

	 var x = d3.time.scale().domain([minDate, maxDate]).range([0, w]);

	// X scale will fit all values from data[] within pixels 0-w
	 //var x = d3.scale.linear().domain([0, data.length]).range([0, w]);
	 // Y scale will fit values from 0-10 within pixels h-0 (Note the inverted domain for the y-scale: bigger is up!)
	 var y = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.trendingValue; } )]).range([h, 0]);

	// create a line function that can convert data[] into x and y points
	 var line = d3.svg.line()
	 // assign the X function to plot our line as we wish
	 .x(function(d, i) {
	 // return the X coordinate where we want to plot this datapoint
	 return x(getDate(d)); //x(i);
	 })
	 .y(function(d) {
	 // return the Y coordinate where we want to plot this datapoint
	 return y(d.trendingValue);
	 });

	 function xx(e) { return x(getDate(e)); };
	 function yy(e) { return y(e.trendingValue); };

	$("#chart").append("<p><small><em>Please move the mouse over data points to see details.</em></small></p>");

	// Add an SVG element with the desired dimensions and margin.
	 var graph = d3.select("#chart").append("svg:svg")
	 .attr("width", w + m[1] + m[3])
	 .attr("height", h + m[0] + m[2])
	 .append("svg:g")
	 .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

	// create yAxis
	 var xAxis = d3.svg.axis().scale(x).ticks(d3.time.months, 1).tickSize(-h).tickSubdivide(true);
	 // Add the x-axis.
	 graph.append("svg:g")
	 .attr("class", "x axis")
	 .attr("transform", "translate(0," + h + ")")
	 .call(xAxis);

	// create left yAxis
	 var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left"); //.tickFormat(formalLabel);
	 // Add the y-axis to the left
	 graph.append("svg:g")
	 .attr("class", "y axis")
	 .attr("transform", "translate(-25,0)")
	 .call(yAxisLeft);

	// Add the line by appending an svg:path element with the data line we created above
	 // do this AFTER the axes above so that the line is above the tick-lines
	 graph
	 .selectAll("circle")
	 .data(data)
	 .enter().append("circle")
	 .attr("fill", "steelblue")
	 .attr("r", 5)
	 .attr("cx", xx)
	 .attr("cy", yy)
	 .on("mouseover", function(d) { showData(this, d.trendingValue);})
	 .on("mouseout", function(){ hideData();});

	 graph.append("svg:path").attr("d", line(data));
	 graph.append("svg:text")
	 .attr("x", -200)
	 .attr("y", -90)
	 .attr("dy", ".1em")
	 .attr("transform", "rotate(-90)")
	 .text("Trending Value");


	 $("#chart").append("<div class='infobox' style='display:none;'>Test</div>");
	 }

	var draw = function() {
	 var data = [ {'date': "2012-10-01", 'trendingValue': 1000}, {'date': "2012-09-01", 'trendingValue': 900}, {'date': "2012-08-01", 'trendingValue': 1100}, {'date': "2012-07-01", 'trendingValue': 950}, {'date': "2012-06-01", 'trendingValue': 1050}];
	 drawChart(data);
	 }
	 </script>
	 <style>
	 #chart path {
	 stroke: steelblue;
	 stroke-width: 2;
	 fill: none;
	 }
	 .axis { shape-rendering: crispEdges; }
	 .x.axis line { stroke: lightgrey; }
	 .x.axis .minor { stroke-opacity: .5; }
	 .x.axis path { display: none; }
	 .y.axis line, .y.axis path {
	 fill: none;
	 stroke: #000;
	 }
	 .infobox {
	 border:2px solid steelblue;
	 border-radius:4px;
	 box-shadow:#333333 0px 0px 10px;
	 margin:200px auto;
	 padding:5px 10px;
	 background:rgba(255, 255, 255, 0.8);
	 position:absolute;
	 top:0px;
	 left:0px;
	 z-index:10500;
	 font-weight:bold;
	 }
	 </style>
	 </head>
	 <body onload="draw();">
	 <div id="chart">
	 </div>
	 </body>
	</html>