While introducing myself to the fantastic data visualization library d3.js I figured I might as well post some of the things I’ve learned.

I needed a responsive line graph with just a little bit of animation to give my graph some life. I also wanted to be able to see details of the exact plot points on the graph. Lastly I wanted the graph to be able to animate if the data was ever swapped out for new data. After a little bit of work the result was the following graph below. The code is far from perfect but it’s definitely a starting point.

See the Pen d3.js Simple Responsive Line Graph with Animation by Tawin Kiethanom (@tawink) on CodePen.

**Breaking down the basic line graph code.**

This graph is made up of a few parts:

- Data (JS array)
- Axes (X axis and Y axis)
- Line (svg path with stroke)
- Area (the filled path area under the line)
- Dots (with detail popup)

function init(){ chartContainer = d3.select('.chart-container'); svg = chartContainer.append('svg'); marginContainer = svg.append('g').attr('class', 'margin-container'); }

These 3 lines initialize our chart by selecting the designated div, appending the SVG element and adding a `marginContainer`

in the SVG. The `marginContainer`

will add padding to all our content, coming right up.

svg.attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); marginContainer .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); x = d3.time.scale().range( [ 0, width ] ); y = d3.scale.linear().range( [ height, 0 ] ); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.value; }) * 1.25]);

In our `render()`

function we setup the dimensions of our SVG and `marginContainer`

. See how the margins are used to get the total width of the SVG and shift the `marginContainer`

over. This provides space for our Axes in the near future. `x`

and `y`

are defined as a scale of time and numbers respectively. Domain is basically the min and max numbers of our graph. For our `x axis`

we want to show only the dates from the given dataset. For the `y axis`

we want to start from 0 and go up to about 125% of the maximum number, this gives us some padding on the top of the chart.

area = d3.svg.area() .x( function( d ) { return x( d.date ); } ) .y0( height ) .y1( function( d ) { return y( d.value ); } ); line = d3.svg.area() .x( function( d ) { return x( d.date ); } ) .y( function( d ) { return y( d.value ); } ); startData = data.map( function( datum ) { return { date : datum.date, value : 0 }; }); xAxis = d3.svg.axis() .scale(x) .orient('bottom'); yAxis = d3.svg.axis() .scale(y) .orient('left');

Now we need functions to generate area and line. For area we need to generate a vertical sliver. So the first point `y0`

is the height because everything is reversed when you’re working with SVG. The coordinates 0,0 start in the top left corner. So `y0`

is essentially from the bottom. `y1`

is the height of our data point. The line function is similar but we just need a point so its the `x`

and `y`

value. Then initialize the `startData`

to zeroes and setup our `xAxis`

and `yAxis`

.

marginContainer.append('g') .attr('class', 'x axis') .attr('transform', 'translate(0,' + height + ')') .call(xAxis); marginContainer.append('g') .attr('class', 'y axis') .call(yAxis) .append('text') .attr('transform', 'rotate(-90)') .attr('y', '1.5em') .style('text-anchor', 'end') .text('Price ($)'); marginContainer.append( 'path' ) .datum( startData ) .attr('class', 'line') .attr( 'd', line ) .transition() .duration( 500 ) .ease('quad') .attrTween( 'd', function() { var interpolator = d3.interpolateArray( startData, data ); return function( t ) { return line( interpolator( t ) ); } } ) .each('end', function() { drawCircles( data, marginContainer ); }); marginContainer.append( 'path' ) .datum( startData ) .attr('class', 'area') .attr( 'd', area ) .transition() .duration( 500 ) .ease('quad') .attrTween( 'd', function() { var interpolator = d3.interpolateArray( startData, data ); return function( t ) { return area( interpolator( t ) ); } } );

Now we append all our parts, `x axis`

, `y axis`

, `line`

and `area`

. We append the `x axis`

as a g element. We vertically translate it down to the bottom of the chart using the height (remember reversed coordinates). Then we call our previously create `xAxis`

which creates the tick marks with values. The `y axis`

doesn’t need to be translated, but we add a small text element.

The `line`

and `area`

are going to be animated. To start we append a path using the initial `startData`

. `transition()`

tells the element theres going to be a transition. `attrTween()`

is where the animation actually happens through interpolation. We want to go from zero to our data value so we pass in `startData`

and `data`

. You’ll notice after we append the line we also run a function called `drawCircles()`

.

We’ll get into appending circles and finishing off our chart in the next post. Cheers!

Check out Part 2.