Tutorial Steps taken from interactive demo here: https://www.rtfmanual.io/d3garden
D3 uses SVG (Scalable Vector Graphics) to draw its elements.
Create an area to create the visualization in.
<div class="canvas"><div>
This can be done with the following statement:
var svg = d3.select('div.canvas').append('svg').attr('width', '648px').attr('height', '452px');
This takes advantage of D3’s chaining. Breaking the statement down:
1. Select the canvas. var svg = d3.select('div.class')
2. Append the svg. .append('svg')
3. Set width and height. .attr('width', '648px')
.attr('height', '452px')
selectAll()
declares a more specific group where you will be adding elements.
selectAll()
creates an empty set that will later be filled with elements.
svg.selectAll('rect.colorBar')
This statement looks for all rect elements (SVG) with class 'colorBar'. If there are none, it creates an empty set.
data()
declares the object or array you will use for the visualization. Your actual dataset is passed to it.
data()
and its argument sets the data that will be iterated through. This creates a series of elements, one for
each item in the dataset.
Check out the properties of each element. These are what can be assigned to attributes of the SVG elements for your graph.
var tomatoes = [
{"width":25,"height":86,"color":"red"},
{"width":25,"height":84,"color":"red"},
{"width":25,"height":98,"color":"red"},
{"width":25,"height":93,"color":"red"},
{"width":25,"height":68,"color":"red"},
{"width":25,"height":70,"color":"red"},
{"width":25,"height":76,"color":"red"},
{"width":25,"height":77,"color":"red"},
{"width":25,"height":95,"color":"red"},
{"width":25,"height":100,"color":"red"},
{"width":25,"height":90,"color":"red"},
{"width":25,"height":75,"color":"red"},
{"width":25,"height":65,"color":"red"},
{"width":25,"height":80,"color":"red"},
{"width":25,"height":78,"color":"red"},
{"width":25,"height":76,"color":"red"},
{"width":25,"height":94,"color":"red"},
{"width":25,"height":78,"color":"red"},
{"width":25,"height":69,"color":"red"},
{"width":25,"height":93,"color":"red"},
]
svg.selectAll('rect.colorBar').data(tomatoes)
data()
declares the object or array for iteration.
enter()
performs the data join and returns the subset of new entries.
svg.selectAll('rect.colorBar').data(tomatoes).enter()
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
append()
determines the type of visualization based on what it's passed.
append()
allows you to choose from the
7 basic SVG elements or a 'g' element.
A 'g' element groups SVG shapes together.
In this case, we want a 'rect' element to build a bar graph.
svg.selectAll('rect.colorBar').data(tomatoes)
.enter().append('rect')
We are close to building the bar graph! So far, we've defined data, selected the empty set of rect elements of class bar, added the dataset, joined the data with the empty set, and added a rect element for each item in the data.
var tomatoes = [
{"width":25,"height":86,"color":"red"},
{"width":25,"height":84,"color":"red"},
{"width":25,"height":98,"color":"red"},
{"width":25,"height":93,"color":"red"},
{"width":25,"height":68,"color":"red"},
{"width":25,"height":70,"color":"red"},
{"width":25,"height":76,"color":"red"},
{"width":25,"height":77,"color":"red"},
{"width":25,"height":95,"color":"red"},
{"width":25,"height":100,"color":"red"},
{"width":25,"height":90,"color":"red"},
{"width":25,"height":75,"color":"red"},
{"width":25,"height":65,"color":"red"},
{"width":25,"height":80,"color":"red"},
{"width":25,"height":78,"color":"red"},
{"width":25,"height":76,"color":"red"},
{"width":25,"height":94,"color":"red"},
{"width":25,"height":78,"color":"red"},
{"width":25,"height":69,"color":"red"},
{"width":25,"height":93,"color":"red"},
]
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
attr()
statements define the properties of each bar. The attributes specific to each type of SVG element can be
reviewed here.
.attr('width' , function (d,i) { return d.width })
attr()
statements define how you want your bars to appear. Specifically, they can be assigned properties of data points.
Continue defining each element’s attributes with height.
.attr(‘height’ , function (d,i) { return d.height })
In the statement function(d,i)
, d
represents items in the data and i
is the index of
elements, beginning at 0.
Separate bars from each other. When new bars are created from a dataset they are set to coordinates of (0, 0) so we have to set some attributes to separate them. You will likely want your bar graph data already ordered by your x-axis values.
.attr('x' , function (d,i) { return i * d.width })
The last statement created a bunch of bars stacked on top of each other. This is because of the default values for the attributes. We have to define x values for this type of bar chart for them to be spaced out appropriately. To space them out we can multiply the index of each bar by the width of the bars to spread them out.
The origin is the top left corner so the bars are likely upside down.
.attr('y' , function (d,i) { return divHeight - d.height })
Since the start point (origin) for D3 is the top left corner of the div, bar charts will come down from the top of the div.
So, how do we fix this?
We need to set a new starting point. To do this, we subtract the bar height from the overall height. This fixes the problem!
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')
This is not the code that creates the bar chart at the top of the page.
Before we add an axis to the graph, we need to define the start and end point of the graph.
var xScale = d3.scale.linear()
.domain( [0, data.length] )
.range( [0, width] );
d3.scale.linear()
= Indicates your scale will be linear across the range specified, 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.
Before we add an axis to the graph, we need to define the start and end point.
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 specified, 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.
Now that we have scales, we can append()
them as elements in the DOM.
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.
Now we can use an append()
statement to get this axis on the graph.
svg.append("g").call(xAxis);
.append("g")
= An axis isn't just a line; it can also have text for labels and tick marks. Since it has multiple
elements to it, this would be a 'g' element in SVG.
.call(xAxis)
= This will define the axis based on what's in the xAxis function.
Now that we have scales, we can turn them into elements in the DOM.
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 we want to use the xScale we already specified.
.orient("left")
= Specifies that this will be a vertical axis, from bottom to top.
Now we can use an append()
statement to get this axis on the graph.
svg.append("g").call(yAxis);
.append("g")
= An axis isn't just a line; it can also have text for labels and tick marks. Since it has multiple
elements to it, this would be a 'g' element in SVG.
.call(yAxis)
= This will define the axis based on what's in the xAxis function.
More information about axes, graphs, and D3 in general:
http://alignedleft.com/tutorials/d3/axes
http://alignedleft.com/tutorials/d3
This guide was written as an assignment for Oregon State's CS 290 course. I selected this topic because I am a business intelligence developer working with SAP's platforms including BOBJ (BusinessObjects). My team is fairly new within the company and we are quickly learning our limitations for graphical representations. I plan to leverage what I learned from researching and writing this in development of extensions for use with Design Studio. For those who are unfamiliar, Design Studio makes heavy use of CSS and JavaScript.