Created
October 5, 2011 06:17
-
-
Save sfrdmn/1263780 to your computer and use it in GitHub Desktop.
DAI 523 - Bubble Chart Skeleton Round 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Hey. We're going to continue with this bubble chart we were working on last class. | |
Here is some motivational ASCII. | |
,. _~-., . YOU'RE BEAUTIFUL! | |
~'`_ \/,_. \_ | |
/ ,"_>@`,__`~.) | . | |
| | @@@@' ",! . . ' | |
|/ ^^@ .! \ | / | |
`' .^^^ ,' ' | . . | |
.^^^ . \ / . | |
.^^^ ' . \ | / . ' | |
.,.,. ^^^ ` . .,+~'`^`'~+,. , ' | |
&&&&&&, ,^^^^. . ._ ..__ _ .' '. '_ __ ____ __ _ .. . . | |
%%%%%%%%%^^^^^^%%&&;_,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~=-., | |
&&&&&%%%%%%%%%%%%%%%%%%&&;,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~= | |
%%%%%&&&&&&&&&&&%%%%&&&_,.;^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__, | |
%%%%%%%%%&&&&&&&&&-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-==--^'~=-.,__,.-=~' | |
##mjy#####*"' | |
_,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,.-=~'`^`'~=-.,__,.-=~' | |
~`'^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^`'~=-.,__,.-=~'`^ | |
*/ | |
var w = 800; // width | |
var h = 600; // height | |
var margin = 100; // margin | |
var xlabel = "murder"; // what we want on the x axis | |
var ylabel = "robbery"; // what we want on the y axis | |
var rlabel = "population"; // what we want for the bubble area | |
/* | |
Selection of body, append SVG, give attributes | |
*/ | |
d3.select("body").append("svg:svg") | |
.attr("width", w+margin) | |
.attr("height", h+margin) | |
.attr("class","chart"); | |
/* | |
Selection of SVG, append group (will group our entire chart), give attributes | |
*/ | |
var chart = d3.select(".chart").append("svg:g") | |
.attr("class","content") | |
.attr("transform", "translate(" + margin/2 + "," + margin/2 + ")"); // The transform with trasnlate will shift our group down and to the right | |
/* | |
The following statement creates a line for our x axis | |
*/ | |
chart.append("svg:line") | |
.attr("stroke-width", 1) | |
.attr( "stroke","gray") | |
.attr("x1", 0) | |
.attr("y1", h) | |
.attr("x2", w) | |
.attr("y2", h); | |
/* | |
The following statement creates a line for our y axis | |
*/ | |
chart.append("svg:line") | |
.attr("stroke-width", 1) | |
.attr( "stroke","gray") | |
.attr("x1", 1) | |
.attr("y1", 0) | |
.attr("x2", 1) | |
.attr("y2", h-1); | |
/* | |
This line takes comma delimited data (aka CSV data) and turns it into | |
JSON (same as Mr. Data Converter). The data is held in a variable named 'csv'. All lines within the | |
curly brackets have access to the data. To use the data, we simply bind it to a selection | |
(using selection.data(csv)) This means all the data in our csv variable is tied to the | |
selection. | |
The 'csv' variable (the data) is just a list of pieces of data. Each piece contains a 'state' | |
value ,a 'population' value, a 'murder' value and so on. And likewise, each piece has (or will have when | |
we append) a corresponding visual element on the screen. | |
If we want the appearance of our visual element to change based on its personal piece of | |
data, we need to give d3 a function. This tells d3, instead of applying the same value | |
to all the visual elements in our selection, apply a different value to each indivdual element | |
according to a ruleset (a function). | |
It is important to remember that your function takes two objects (thingies [pieces]) as input, one | |
is the data object for a given element, and the other is the element's position in the selection | |
(zeroth circle, first circle, second circle, third, etc) | |
Zeroth Circle is also probably a metal band. | |
Our functions will be written in this format: | |
var name = function(d,i) { | |
return "some kinda thing"; | |
} | |
This creates the function. In order to use it, you must plug it in to d3. | |
*/ | |
d3.csv( "data/crimeRatesByState2005.csv", function(csv) { | |
/* | |
The the following two thingamadudes are d3's way of helping you out by creating | |
functions for you. xgrid and ygrid now contain functions created by d3. | |
All these do is relate the range of the data (all possible values) to the | |
range of the chart size. A data value which is around 50% of the largest | |
data value should correspondingly be placed around the center of the chart | |
(50% of max width and/or height). | |
*/ | |
var xMax = d3.max( csv.map( function(d) { | |
return parseFloat(d[xlabel]); | |
})); | |
console.log(xMax); | |
var yMax = d3.max( csv.map( function(d) { | |
return parseFloat( d[ylabel] ); | |
})); | |
var xgrid = d3.scale.linear() | |
.domain([0.0,xMax]) // range of data | |
.range([0.0,w]); // range of width | |
// 0 in, 0 out | |
// 10 in, w out | |
/* NOTE: Code from last time was false here. | |
For our y values, we want data of value 0 to be at the bottom of the chart, | |
therefore 0 should correspond to h (y-axis increases top down) and our max value | |
should correspond to zero. | |
*/ | |
var ygrid = d3.scale.linear() | |
.domain([0.0,yMax]) // range of data | |
.range([h,0.0]); // range of height | |
// 0 in, h out | |
// 260 in, 0 out | |
var colorScale = d3.scale.linear() | |
.domain([0,500]) | |
.range(["rgb(200,200,200)", "rgb(20,20,20)"]); | |
/* | |
Here are the functions we wrote. 'd' and 'i' are our inputs. For any given circle, | |
'd' is its piece of data and 'i' is its position in the selection. To access values | |
in a data piece (data object) just be all like d.whatever or d["whatever"]. They | |
do the same thing. In the bracket version you can put a variable inside to make | |
it more dynamic. We're going to do that below: | |
*/ | |
var radius = function(d,i) { | |
return Math.sqrt( d[rlabel] ) / 150; // FUN FACT: we could use another scale function here instead of arbitrarily using 150 | |
} | |
var xpos = function(d,i) { | |
return xgrid( d[xlabel] ); // d.murder in, corresponding x value out | |
} | |
var ypos = function(d,i) { | |
return ygrid( d[ylabel] ); // d.robbery in, corresponding x value out | |
} | |
var color = function(d,i) { | |
return colorScale( d["aggravated_assault"] ); | |
} | |
/* | |
This is the code which places the bubbles. | |
First, it makes an empty selection of all circles named bubble (none exist yet). | |
Then it attaches our dataset to that selection. | |
For every member in that dataset, it adds a new circle to the image. | |
After that, it is only a matter of adding attributes to those bubbles. | |
*/ | |
chart.selectAll("circle.bubble").data(csv) | |
.enter().append("svg:circle") | |
.attr("class", "bubble") | |
.attr("cx", xpos ) | |
.attr("cy", ypos ) | |
.attr("r", radius ) | |
.attr("fill", color ); | |
/* | |
The following statements create grid lines | |
You can reuse this later if you need to. Only thing, is it uses our | |
ygrid and xgrid functions. In another visualisation, if you name your | |
x and y scale functions something else, you'll have to rename it in the | |
grid line code too. | |
*/ | |
chart.selectAll("line.xgrid").data( xgrid.ticks(10) ) | |
.enter().insert("svg:line", "circle") | |
.attr("class", xgrid) | |
.attr("stroke-width", .5) | |
.attr("stroke", "lavender") | |
.attr("x1", xgrid) | |
.attr("y1", 0 ) | |
.attr("x2", xgrid) | |
.attr("y2", h-1 ); | |
chart.selectAll("line.ygrid").data( ygrid.ticks(10) ) | |
.enter().insert("svg:line", "circle") | |
.attr("class", "ygrid") | |
.attr("stroke-width", .5) | |
.attr("stroke", "lavender") | |
.attr("x1", 0) | |
.attr("y1", ygrid) | |
.attr("x2", w-1) | |
.attr("y2", ygrid); | |
var page = d3.select("body"); | |
page.append("div") | |
.attr("class", "xlabel") | |
.style("width", w + "px" ) | |
.style("height", 30 ) | |
.style("text-align", "center") | |
.append("p") | |
.text( xlabel ); | |
page.append("div") | |
.attr("class", "ylabel") | |
.style("width", 30 ) | |
.style("height", h + "px" ) | |
.style("position", "absolute") | |
.style("left", "0px" ) | |
.style("top", "300px") | |
.append("p") | |
.text( ylabel ); | |
// The following lines create the labels for our axes. Uses the same method as making grid | |
chart.selectAll("text.xrule").data( xgrid.ticks(10) ) | |
.enter().append("svg:text") | |
.attr("class", "xrule") | |
.attr("x", xgrid) | |
.attr("y", h ) | |
.attr("dx", -7 ) | |
.attr("dy", 15 ) | |
.text( function(d) { | |
return d; | |
}); | |
chart.selectAll("text.yrule").data( ygrid.ticks(10) ) | |
.enter().append("svg:text") | |
.attr("class", "yrule") | |
.attr("x", 0) | |
.attr("y", function(d,i) { | |
return ygrid(d,i); | |
}) | |
.attr("dx", -25) | |
.attr("dy", 5 ) | |
.text( function(d,i) { | |
if( i != 0 ) | |
return d; | |
else | |
return ""; | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment