SVG, or Scalable Vector Graphic, is an XML language used to draw graphics. Typically Adobe
Illustrator or a free tool like Inkscape
is used to draw them.
Rather than being raster based like typical pictures, they are vector based. As you zoom in
and out, they scale and do not get pixellated. For more info on the difference, you can go
here.
These are relevant to D3 because they're what's used to draw visualizations: lines, circles, rectangles.
Attribute | Description |
---|---|
x1 | x-axis coordinate of the start of the line |
y1 | y-axis coordinate of the start of the line |
x2 | x-axis coordinate of the end of the line |
y2 | y-axis coordinate of the end of the line |
Attribute | Description |
---|---|
cx | x-axis coordinate of the center |
cy | y-axis coordinate of the center |
r | radius of the element |
Attribute | Description |
---|---|
x | x-axis coordinate |
y | y-axis coordinate |
width | horizontal length |
height | vertical length |
rx | x-axis radius of the ellipse used to round off the corners of the rectangle |
ry | y-axis radius of the ellipse used to round off the corners of the rectangle |
stroke
elementCode examples from https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke
Stroke is a presentation element, so it's most often used to style the other attributes.
For a colored line:
<svg height="50" width="300">
<path stroke="orange" d="M5 20 1215 0" />
</svg>
To create a circle with a border, you would do something like this:
<svg height="50" width="300">
<path stroke="orange" d="M5 20 1215 0" />
</svg>
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="blue" stroke-width="2" fill="black" />
</svg>
This is an especially useful feature for charts when you want borders on the items.
The D3 graphic above is actually an embedded SVG.
<svg width="96" height="91">
<clipPath id="clip">
<path d="M0,0h7.75a45.5,45.5 0 1 1 0,91h-7.75v-20h7.75a25.5,25.5 0 1 0 0,-51h-7.75zm36.2510,0h32a27.75,27.75 0 0 1 21.331,45.5a27.75,27.75 0 0 1 -21.331,45.5h-32a53.6895,53.6895 0 0 0 18.7464,-20h13.2526a7.75,7.75 0 1 0 0,-15.5h-7.75a53.6895,53.6895 0 0 0 0,-20h7.75a7.75,7.75 0 1 0 0,-15.5h-13.2526a53.6895,53.6895 0 0 0 -18.7464,-20z"></path>
</clipPath>
<linearGradient id="gradient-1" gradientUnits="userSpaceOnUse" x1="7" y1="64" x2="50" y2="107">
<stop offset="0" stop-color="#f9a03c"></stop>
<stop offset="1" stop-color="#f7974e"></stop>
</linearGradient>
<linearGradient id="gradient-2" gradientUnits="userSpaceOnUse" x1="2" y1="-2" x2="87" y2="84">
<stop offset="0" stop-color="#f26d58"></stop>
<stop offset="1" stop-color="#f9a03c"></stop>
</linearGradient>
<linearGradient id="gradient-3" gradientUnits="userSpaceOnUse" x1="45" y1="-10" x2="108" y2="53">
<stop offset="0" stop-color="#b84e51"></stop>
<stop offset="1" stop-color="#f68e48"></stop>
</linearGradient>
<g clip-path="url(#clip)">
<path d="M-100,-102m-27,0v300h300z" fill="url(#gradient-1)"></path>
<path d="M-100,-102m27,0h300v300z" fill="url(#gradient-3)"></path>
<path d="M-100,-102l300,300" fill="none" stroke="url(#gradient-2)" stroke-width="40"></path>
</g>
</svg>
For more info on SVG: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Introduction
Browser Compatibility: http://caniuse.com/#feat=svg
Full Element List: https://developer.mozilla.org/en-US/docs/Web/SVG/Element
This works similarly to jQuery collections of elements.D3 traverses the nodes in the DOM to return those matching the criteria
There are two primary methods: d3.select and d3.selectAll.
d3.select('div');
d3.selectAll('div');
d3.select('#tree');
# is used to signify an ID.
Chaining is allowed until there's a return.
d3.select('div').style('color', 'orange');
d3.select('div').style({'color' : 'blue', 'font-size' : '40px'}).attr();
d3.select('element.class');
d3.select('element#id');
d3.select('.class');
.classed('class');
returns true or false.
For more on selections, especially on classed()
, go here.
Another major feature of D3 to preview is how to bind data. This is a full example from Wikipedia. Let's take a closer look at what's happening in the code.
// Data
var data = [
{ name:"Ireland", income:53000, life: 78, pop:6378, color: "green"},
{ name:"Norway", income:73000, life: 87, pop:5084, color: "blue" },
{ name:"Tanzania", income:27000, life: 50, pop:3407, color: "grey" }
];
// Create SVG container
var svg = d3.select("#hook").append("svg")
.attr("width", 120)
.attr("height", 120)
.style("background-color", "#D0D0D0");
// Create SVG elements from data
svg.selectAll("circle") // create virtual circle template
.data(data) // bind data
.enter() // for each row in data...
.append("circle") // bind circle & data row such that...
.attr("id", function(d) { return d.name }) // set the circle's id according to the country name
.attr("cx", function(d) { return d.income /1000 }) // set the circle's horizontal position according to income
.attr("cy", function(d) { return d.life }) // set the circle's vertical position according to life expectancy
.attr("r", function(d) { return d.pop /1000 *2 }) // set the circle's radius according to country's population
.attr("fill",function(d){ return d.color }); // set the circle's color according to country's color
Here we have data defined with 5 different attributes per item:
// Data
var data = [
{ name:"Ireland", income:53000, life: 78, pop:6378, color: "green"},
{ name:"Norway", income:73000, life: 87, pop:5084, color: "blue" },
{ name:"Tanzania", income:27000, life: 50, pop:3407, color: "grey" }
];
Using what we learned about selections earlier, you would select the HTML element onto which
you'd like to append. This snippet utilizes chaining.
d3.select("#hook").append("svg")
selects the HTML element with id hook and appends an svg element to it.
.attr("width", 120)
This sets the width attribute of the svg to 120.
.attr("height", 120)
This sets the height attribute of the svg to 120.
.style("background-color", "#D0D0D0");
This sets the background-color of the svg.
// Create SVG container
var svg = d3.select("#hook").append("svg")
.attr("width", 120)
.attr("height", 120)
.style("background-color", "#D0D0D0");
Order matters. This selects the empty set of circles and creates data circles for each data point. There is some good information on this here from one of the authors of the D3 library.
svg.selectAll("circle")
circle is an empty set, but it says that you want circles.
.data(data)
binds, or joins, the data to your selection.
.enter()
returns an empty placeholder for each new data element that's not yet in the DOM.
.append("circle")
appends a new circle for each new data element in the selection from enter
.
The rest of the lines assign specific attributes of the data points to the circles.
// Create SVG elements from data
svg.selectAll("circle") // create virtual circle template
.data(data) // bind data
.enter() // for each row in data...
.append("circle") // bind circle & data row such that...
.attr("id", function(d) { return d.name }) // set the circle's id according to the country name
.attr("cx", function(d) { return d.income /1000 }) // set the circle's horizontal position according to income
.attr("cy", function(d) { return d.life }) // set the circle's vertical position according to life expectancy
.attr("r", function(d) { return d.pop /1000 *2 }) // set the circle's radius according to country's population
.attr("fill",function(d){ return d.color }); // set the circle's color according to country's color
Inclusion of update
and exit
will allow for dynamic visualizations. An example of this from Mike's data joins
article linked above:
var circle = svg.selectAll("circle")
.data(data);
circle.exit().remove();
circle.enter().append("circle")
.attr("r", 2.5)
.merge(circle)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
He has written other examples with update
here.
This doesn't cover all types, but here are some you're likely to see.
d3.json('phones.json', function(error, data) {
// do something with the data here
console.log(error);
console.log(data);
});
d3.csv('climate_data.csv', function(data) {
debugger;
});
The console is extremely helpful for testing out D3 functions. Keep in mind that you can call functions by typing them into the console.
If your graphs are not rendering, check the version of D3 you're including and try moving the script call to the body. These are things I ran into when creating the demos.
I was unable to get the axes working correctly for the bar chart example I found and the others were overly complex for what I was trying to find.
I also found that you have to be careful when writing your scripts. I wanted to have a couple different charts on my bar graph page but found that they didn't play nice with each other. However, with the scatterplot script this was not an issue. This is the type of code I would use as a resource for building extensions in the future since it's proven to be scaleable and doesn't appear to have problems with multiple graphs on the page which could definitely be an issue in a dashboard.
You'll see that a number of the examples on the example page are hosted at bl.ocks.org. To host your code there, you actually use Gist.
Add all of your relevant files: html, js, and data. Your gist will be assigned a URL. From that URL, replace gist.github.com with bl.ocks.org to get the rendered page.
I tried this, copying another existing project:
https://gist.github.com/sarahmaas/d2cb92ad058330fa9f93f232d2ba161b
https://bl.ocks.org/sarahmaas/d2cb92ad058330fa9f93f232d2ba161b
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.