Learn D3.js Basics By Planting A Vegetable Garden

Master the fundamentals of D3 with this interactive tutorial

Get Started

D3 Garden

Give Feedback

Set the bounds for your garden!

Resize this box to begin to your preferred bounds to begin

Current Graph

Welcome to the D3 Garden

This tutorial will help you learn the major principles of D3 so you can easily build custom graphs.

Why do I need this?

Picking up D3 can be very challenging. It relies on a novel challenge for developers- converting an array or object into a dynamic data visualization with specific properties.

What is the focus?

This tutorial aims to make D3 so simple that you can explain it to a friend. We will build a basic bar graph using a gardening analogy so you can see the principles play out in front of you.

What do I need to know first?

You must know HTML/CSS, and have at least a beginner's understanding of Javascript. You must understand concepts like "for" loops, objects and arrays.

Go to Step 1

Step 1/13: The SVG Canvas

D3 uses SVG (Scalable Vector Graphics) to draw its elements.

Stake out your garden

We need to declare an area to create our visualization. Drag the resizable box to create your bounded area. You will want a big garden!

Garden Dimensions:

Back
Go to Step 2

Please make your box at least 410 x 410

Step 2/13: Declare SVG

Learn how to create the SVG in D3

How to define the canvas

var svg = d3.select('div.foo').append('svg')
.attr('width' , 'Xpx' ).attr('height' , 'Ypx' );

d3.select('div.foo')
= Equivalent of jQuery $(), select the container with class foo
.append('svg')
= Append an SVG element to the DOM
.attr('width' , 'Xpx' )
= Declare an attribute for your SVG, then set value

Your turn!

var svg =

Your container div has class 'gardenDiv'

Append the svg

Declare a width of 0px

Declare a height of 0px

Docs

Back
Go to Step 3

Please enter all fields and correct pixel amounts

Step 3/13: selectAll() Statement

selectAll() declares a more specific group where you will be adding elements

What It Does

selectAll() creates an empty set that will later be filled with elements. It is technically infinite, but we will portray it as finite for the sake of visualizing it.

In The Garden

selectAll() creates holes that you will be filling with seeds of a specific type. You cannot dig holes where other elements have already been created, so this must be a new set of elements

Docs

Back
Go to Step 4

Step 4/13: selectAll() in action

Dig those holes!

How to use selectAll()

svg.selectAll('rect.bar')

This statement looks for all rect elements (from SVG specification) with class 'bar'. If there are none, it creates an empty set.

Your turn!

svg

Create an empty set of rect elements with class 'colorBar'

Docs

Back
Dig The Holes

Please use selectAll() with rect elements of class 'colorBar'

Step 5/13: data() Statement

data() declares the object or array you will use for the visualization

What It Does

data() determines the data that you will then iterate through in order to create a series of elements

In The Garden

data() is the type of seeds you will be using- each seed type has unique properties that will determine its features when it grows into a plant

Docs

Select your seeds

Tomatoes

Select

Cucumbers

Select

Peppers

Select

Step 6/13: Add data()

Check out the properties

How to use data()

svg.selectAll('rect.bar').data(data)

Data() declares the object or array you will be iterating through. Pretty straightforward.

Your turn!

svg.selectAll('rect.bar')

Add the data contained in the variable tomatoes

Docs

Back
Go To Step 7

Please make sure the variable matches the object above

Step 7/13: enter() the data

Enter() performs the data join

svg.selectAll('rect.bar').data(data).enter()

What It Does

enter() combines your data with the empty set from selectAll() and creates a set of elements that can then be accessed one by one in D3

In The Garden

This adds the seeds you selected in the past step to the garden, and matches the number of holes with number of plants. There are now 20 seeds in holes ready to be structured.

Your turn!

svg.selectAll('rect.bar').data(data)

Add your enter statement, that is it!

Docs

Show Full Array

Back
Plant the Seeds

Please make sure you used the enter statement

Step 8/13: append() the element

Append() determines the type of visualization

What It Does

Append() allows you to choose from the 7 basic SVG elements or a 'g' element. In this case, we want a 'rect' element to build a bar graph.

In The Garden

You want the seeds you planted to grow in a defined way. We will add complementary structures like trellises to the garden to help our plants grow vertically.

svg.selectAll('rect.bar').data(data)
.enter().append('rect')

Your turn!

svg.selectAll('rect.bar').data(data).enter()

Append a rect element for each item in your data

Docs

Show Full Array

Back
Add The Structure

Please make sure you appended a 'rect' element

Step 9/13: Quick Review

We are close to building a bar graph!

How to define each bar

svg.selectAll('rect.bar').data(data)
.enter().append('rect')

svg.selectAll('rect.bar')
= Creates an empty set of rect elements with class 'bar'
.data(data)
= Adds object or array of data to be turned into elements in the DOM
.enter()
= Join your data with the empty set defined in selectAll, can iterate through this set
.append('rect')
= Append a 'rect' element for every item in data
Back
Let's Grow The Plants

Step 10/13: Define Bar Width

Attr() statements define the properties of each bar

What It Does

.attr('width' , function (d,i) { return d.width })

Attr() statements define what you want your bars to look like. Most importantly, they can use properties from each item in data.

In The Garden

We will do the width first, so this will define the width of each plant.

Your turn!

Write out the statement above, which defines the width based on the 'width' property of each item in the data object

Docs

Show Full Array

Back
Define The Height

Please make sure you copied the statement above

Step 11/13: Define Bar Height

Define each element's attributes

What It Does

.attr('height' , function (d,i) { return d.height })

In the statement 'function(d,i)', d stands for each item in data while i is the index, beginning at 0 for the first element

In The Garden

Now each plant will have a different height based on the object's properties

Your turn!

Write out the statement above, which defines the height based on the 'height' property of each item in the data object

Docs

Show Full Array

Back
How To Position The Plants

Please make sure you copied the statement above

Step 12/13: Put Bars In A Row

Separate bars from each other

What It Does

.attr('x' , function (d,i) { return i * d.width })

In last statement we ended up with... a bunch of plants stacked on top of one another. That was disappointing. We also need to define x values for each bar so that they do not stack on top of each other, like they did in the last step.

Using the index of each bar, we can move them right to spread them out. We can multiply this index by the width of each bar to spread them out.

In The Garden

Now each plant will align with the appropriate structure as opposed to being stacked on top of each other in the first position.

Your turn!

Write out the statement above, which defines the x-position based on the index and separates based on bar width

Docs

Show Full Array

Back
How To Position The Plants

Please make sure you copied the statement above

Step 13/13: Bar Orientation

The origin is the top left corner... which means your bars may be pointing the wrong direction!

What It Does

.attr('y' , function (d,i) { return divHeight - d.height })

The origin i.e. start point for D3 is the top left corner of the div. This means that when you set the height of a bar... it is growing downwards from the top left! Not good. So, we need to reverse this.

We need to set a new start point for the bar to grow from. We subtract the bar height from the overall height of the div. We start from the bottom of the containing div, and draw the bar starting from there!

Your turn!

Write out the statement above, which defines the y-position based on the height of the svg.

Back
Show Me The Final Graph

Please make sure you copied the statement above

Done! Final Code

                    
var w= 535;
var h= 250;
var svg= d3.select('.gardenDiv')
    .append('svg')
    .attr('width', w)
    .attr('height', h);

svg.selectAll('rect.colorBar')
    .data(data)
    .enter()
    .append('rect')
    .attr('width', function(d,i){
        return d.width
    })
    .attr('height', function(d,i){
        return d.height*2
    })
    .attr('x', function(d,i){
        return i * (d.width+2)
    })
    .attr('y', function(d,i){
        return h - d.height*2
    })
    .attr('fill', 'white')
                    
                
Give Feedback
Add X and Y Axis

Step 14/20: Scale on X Axis

Before we add an axis to the graph, we need to define the start and end point.

How to define a scale

var xScale = d3.scale.linear()
.domain( [0, data.length] )
.range( [0, width] );

d3.scale.linear()
= Indicates your scale will be linear across the range you specify, as opposed to exponential etc.
.domain( [0, data.length] )
= Specifies that the scale ranges from 0 to the count of total number of items in the array
.range( [0, width] )
= Maps the specified domain to corresponding spots on the SVG. In this case, extends the full width of the SVG.

Your turn!

var xScale =

Add a linear scale

Add a domain that spans from 0 to the count of numbers in data

Add a range that spans the width of the SVG

Docs

Back
Add Y Scale

Please make sure you specified domain and range correctly

Step 15/20: Scale on Y Axis

Before we add an axis to the graph, we need to define the start and end point.

How to define a scale

var yScale = d3.scale.linear()
.domain( [0, d3.max(data, function(d) { return d.height; })] )
.range( [0, height] );

d3.scale.linear()
= Indicates your scale will be linear across the range you specify, as opposed to exponential etc.
.domain( [0, d3.max(data, function(d) { return d.height; })] )
= Specifies that the scale ranges from 0 to the tallest bar, which d3.max will find based on the height attribute
.range( [0, height] )
= Maps the specified domain to corresponding spots on the SVG. In this case, extends the full height of the SVG.

Your turn!

var yScale =

Add a linear scale

Add a domain that spans from 0 to the tallest bar

Add a range that spans the height of the SVG

Docs

Back
Create an X Axis

Please make sure you specified domain and range correctly

Step 16/20: Create X Axis, Pt 1

Now that we have scales, we can turn them into elements in the DOM

How to define an axis

var xAxis = d3.svg.axis().scale(xScale)

d3.svg.axis()
= Indicates that we want to create an element with the characteristics of an axis i.e. can have labels and tick marks
.scale(xScale)
= Specifies that we want to use the xScale we already specified

Your turn!

var xAxis =

Add an axis

Add a scale called xScale

Docs

Back
Create an X Axis

Please make sure you specified the scale correctly

Step 17/20: Create X Axis, Pt 2

Now we can use an append statement to get this axis on the graph

How to append an axis

svg.append("g").call(xAxis);

.append("g")
= An axis is not just a line. It can also include ticks and labels. So we will need a "g" element, not a path.
.call(xAxis)
= The characteristics of this axis will be based on the axis we defined

In The Garden

We can now add a fence to our garden

Your turn!

svg

Append a g element

Call xAxis

Docs

Back
Define a Y Axis

Please make sure you called the correct variable

Step 18/20: Create Y Axis, Pt 1

Now that we have scales, we can turn them into elements in the DOM

How to define an axis

var yAxis = d3.svg.axis().scale(yScale)
.orient("left")

d3.svg.axis()
= Indicates that we want to create an element with the characteristics of an axis i.e. can have labels and tick marks
.scale(yScale)
= Specifies that twe wantto use the xScale we already specified
.orient("left")
= Specifies that this will be a vertical axis, from bottom to top

Your turn!

var yAxis =

Add an axis

Add a scale called yScale

Docs

Back
Create a Y Axis

Please make sure you specified the scale correctly

Step 19/20: Create Y Axis, Pt 2

Now we can use an append statement to get this axis on the graph

How to append an axis

svg.append("g").call(yAxis);

.append("g")
= An axis is not just a line. It can also include ticks and labels. So we will need a "g" element, not a path.
.call(yAxis)
= The characteristics of this axis will be based on the axis we defined

In The Garden

We can now add a fence to our garden

Your turn!

svg

Append a g element

Call yAxis

Docs

Back
Add Y Axis

Please make sure you called the correct variable

Step 20/20: Fix X Axis

The x axis needs to be at the bottom of the graph

How to move the axis

So obviously, you would not want the x axis at the top of your graph! Let's use transform to move it to the bottom.

svg.append("g")
.attr("transform", "translate(0," + (height) + ")").call(xAxis);

.attr("transform", "translate(0," + (height) + ")")
= Translate takes two arguments: right and down. This statement moves the axis 0 units right, and moves it downward bythe entire height of the svg. In other words, the bottom

Your turn!

svg.append("g")

Move the axis to the bottom of the SVG

Docs

Back
See Final Graph

Please make sure you called the transform/translate command

Done! Final Code

Give Feedback
                    
var w= 535;
var h= 250;
var svg= d3.select('.gardenDiv')
    .append('svg')
    .attr('width', w)
    .attr('height', h);

svg.selectAll('rect.colorBar')
    .data(data)
    .enter()
    .append('rect')
    .attr('width', function(d,i){
        return d.width
    })
    .attr('height', function(d,i){
        return d.height*2
    })
    .attr('x', function(d,i){
        return i * (d.width+2)
    })
    .attr('y', function(d,i){
        return h - d.height*2
    })
    .attr('fill', 'white')

var xScale = d3.scale.linear()
    .domain( [0, data.length] )
    .range( [0, w] );

var yScale = d3.scale.linear()
    .domain( 
        [0, 
        d3.max(data, function(d) { 
            return d.height; })
        ])
    .range( [0, h] );

var xAxis = d3.svg.axis()
    .scale(xScale)
    .ticks(0)

var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left")
    .ticks(0)

svg.append("g")
    .attr("transform", 
    "translate(5,0)")
    .call(yAxis);

svg.append("g")
    .attr("transform", 
    "translate(0," + (h-5) + ")")
    .call(xAxis);
                    
                
Discover More Popular Tutorials