These are the materials for an introduction to D3.js workshop for the National day of Civic Hacking (Code for SF) attendees.
We will be using the following two tools to works through these exercises:
I would love your feedback on the materials in the Gitter forum or in the Github issues.
And please do not hesitate to reach out to me directly via email at jondinu@gmail.com or over twitter @clearspandex
The data is from Zillow and is calculated according to their methodology.
The files are comma separated with headers with each column representing a given neighborhood in SF:
Month | Mission | Bernal Heights | Excelsior | ... |
---|---|---|---|---|
2014-01 | 4.21124828532236 | 2.32484076433121 | 1.50130548302872 | ... |
2014-02 | 4.13333333333333 | 2.54726368159204 | 1.225 | ... |
2014-03 | 4.54921422663358 | 2.70212765957447 | 2.25225225225225 | ... |
... | ... | ... | ... | ... |
Archival event link: National Day of Civic Hacking 2015: San Francisco
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<script src="/d3/d3.js"></script>
<style>
body {
font-family: futura;
width: 960px;
}
h2.title {
color: black;
text-align: center;
}
.axis {
font-family: arial;
font-size: 0.7em;
}
text {
fill: black;
stroke: none;
}
.label {
font-size: 2em;
}
path {
fill: none;
stroke: black;
stroke-width: 2px;
}
.tick {
fill: none;
stroke: black;
}
.bar {
opacity: 0.9;
stroke: none;
fill: grey;
}
.line {
fill: none;
stroke: #4eb0bb;
stroke-width: 1px;
}
</style>
​
<script type="text/javascript">
// https://github.com/mbostock/d3/wiki/Time-Formatting
//d3.time.format('%Y/%m/%d')(d3.time.format('%m/%d/%Y').parse(d))
format = d3.time.format("%m/%d/%Y");
​
//Call the function to pass the data.
function draw(data) {
"use strict";
//debugger;
// set margins according to Mike Bostock's margin conventions
// https://bl.ocks.org/mbostock/3019563
var margin = {top: 25, right: 40, bottom: 100, left: 75};
// set height and width of chart
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var barPadding = 10;
// specify the radius of our circles and the
// column we want to plot
//Need this to be variable
var field = 'Water';
// Append the title for the graph
d3.select("body")
.append("h2")
.text("Monthly water consumption at city of Palo Alto from yr 2009 to 2016")
.attr('class', 'title');
// append the SVG tag with height and width to accommodate for margins
//mainly to get margin to correctly
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g')
.attr('class','chart')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// remove missing values
data = data.filter(function(d) {
return d[field];
});
// bind our data to svg rects for the bar plot
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
// .append("circle")
.attr('class', 'bar')
// maximum price for rent
var max_y = d3.max(data, function(d) {
//debugger;
console.log(d);
return +d[field];
});
// get min/max dates
var time_extent = d3.extent(data, function(d){
//debugger;
console.log(d);
return format.parse(d['Date']);
});
// Create x-axis scale mapping dates -> pixels
var time_scale = d3.time.scale()
.range([0, width])
.domain(time_extent);
// Create y-axis scale mapping price -> pixels
var measure_scale = d3.scale.linear()
.range([height, 0])
.domain([0, max_y]);
// Create D3 axis object from time_scale for the x-axis
var time_axis = d3.svg.axis()
.scale(time_scale)
.tickFormat(d3.time.format("%b %y"));
// Create D3 axis object from measure_scale for the y-axis
var measure_axis = d3.svg.axis()
.scale(measure_scale)
.orient("left");
// Append SVG to page corresponding to the D3 x-axis
svg.append('g')
.attr('class', 'x axis')
.attr('transform', "translate(0," + height + ")")
.call(time_axis);
// Append SVG to page corresponding to the D3 y-axis
svg.append('g')
.attr('class', 'y axis')
.call(measure_axis);
// add label to y-axis
var y_label = d3.select(".y.axis")
.append("text")
.attr('class', 'label')
.text("CCF (centum cubic feet)")
.style('font-size', '1.2em')
.attr("transform", "rotate(-90)");
// center y axis label
y_label.attr("x", -(height / 2)).attr('y', -60)
.style("text-anchor", "middle");
// based on the data bound to each svg rect,
// change its x, y, width, height accordingly
d3.selectAll('.bar')
.attr('x', function(d) {
return time_scale(format.parse(d['Date']));
})
.attr('width', function(d) {
return (width / data.length - barPadding)*5;
})
.attr('y', function(d) {
return measure_scale(+d[field]);
})
.attr('height', function(d) {
return height - measure_scale(+d[field]);
});
};
</script>
</head>
<body>
<script type="text/javascript">
// load our data file asynchronously and pass the data
// to the draw function once it is loaded.
d3.csv("data.csv", draw);
//1st argument File name
//2nd argument call taht call back function pass all that data
</script>
</body>
</html>