An interactive bar chart of snow totals in the United States, using D3 and some JQuery magic. Used as a walkthrough tutorial at the first Syracuse InfoViz Meetup.
Created
March 2, 2015 22:24
-
-
Save bceskavich/71034078fe6258edd9f0 to your computer and use it in GitHub Desktop.
Syracuse InfoViz Meetup D3 Tutorial
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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>D3 Bar Chart</title> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<style> | |
body { | |
margin: 0px; | |
padding: 0px; | |
font-family: 'Avenir'; | |
} | |
h1 { | |
margin-left: 25px; | |
text-align: left; | |
font-size: 25px; | |
} | |
.main { | |
margin: 0px 25px; | |
} | |
svg { | |
border: 1px dotted black; | |
padding: 20px 40px; | |
} | |
rect { | |
fill: cadetblue; | |
} | |
rect:hover { | |
fill: orange; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
text, | |
.axis text { | |
font-size: 11px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Top Ten Golden Snowglobe Totals (2015), by City</h1> | |
<div class="main"> | |
<p><span id="city">Worcester</span> - <span id="inches">112.2</span>"</p> | |
</div> | |
<script type="text/javascript"> | |
// Wrapper function for the D3 code | |
function render() { | |
/* PART 1 - Dimensions */ | |
// Top 10 Golden Snowglobe cities (as of 3/2/15) | |
var dataset = [ | |
{"city": "Worcester", "snow": 112.2}, | |
{"city": "Syracuse", "snow": 108.5}, | |
{"city": "Buffalo", "snow": 104.8}, | |
{"city": "Boston", "snow": 103.9}, | |
{"city": "Erie", "snow": 103.0}, | |
{"city": "Rochester", "snow": 89.8}, | |
{"city": "South Bend", "snow": 79.2}, | |
{"city": "Grand Rapids", "snow": 75.0}, | |
{"city": "Lakewood", "snow": 67.7}, | |
{"city": "Cleveland", "snow": 65.7} | |
] | |
// Dimensions for the chart: height, width, and space b/t the bars | |
var margins = { | |
top: 30, | |
right: 50, | |
bottom: 30, | |
left: 50 | |
} | |
var height = 400 - margins.left - margins.right, | |
width = 700 - margins.top - margins.bottom, | |
barPadding = 5 | |
/* END Part 1 */ | |
/* PART 4 - Creating the Axes */ | |
// Create a scale for the y-axis based on the snow total amounts | |
// -- Domain - min and max values in the dataset | |
// -- Range - physical range of the scale (reversed) | |
var yScale = d3.scale.linear() | |
.domain([0, d3.max(dataset, function(d){ | |
return d.snow; | |
})]) | |
.range([height, 0]); | |
// Implements the scale as an actual axis | |
// -- Orient - places the axis on the left of the graph | |
// -- Ticks - number of points on the axis, automated | |
var yAxis = d3.svg.axis() | |
.scale(yScale) | |
.orient("left"); | |
// Creates a scale for the x-axis based on city names | |
var xScale = d3.scale.ordinal() | |
.domain(dataset.map(function(d){ | |
return d.city; | |
})) | |
.rangeRoundBands([0, width], .1); | |
// Creates an axis based off the xScale properties | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.orient("bottom"); | |
/* END Part 4 */ | |
/* PART 2 - Drawing the Graph */ | |
// Creates the initial space for the chart | |
// -- Select - grabs the empty <div> above this script | |
// -- Append - places an <svg> wrapper inside the div | |
// -- Attr - applies our height & width values from above; centers | |
var chart = d3.select(".main") | |
.append("svg") | |
.attr("width", width + margins.left + margins.right) | |
.attr("height", height + margins.top + margins.bottom) | |
.append("g") // An SVG container element | |
.attr("transform", "translate(" + margins.left + "," + margins.top + ")"); | |
// For each value in our dataset, places and styles a bar on the chart | |
// Step 1: Draws the bars | |
// -- Loops through the dataset and appends a rectangle for each value | |
chart.selectAll("rect") | |
.data(dataset) | |
.enter() // akin to dataset.forEach() | |
.append("rect") | |
// Step 2: X & Y | |
// -- X - Places the bars horizontally based on our scale | |
// -- Y - Places the bars vertically based on our scale | |
.attr("x", function(d, i){ | |
return xScale(d.city); | |
}) | |
.attr("y", function(d){ | |
return yScale(d.snow); | |
}) | |
// Step 3: Height & Width | |
// -- Width - Based on barpadding and number of points in dataset | |
// -- Height - Scale and height of the chart area | |
.attr("width", (width / dataset.length) - barPadding) | |
.attr("height", function(d){ | |
return height - yScale(d.snow); | |
}) | |
/* END Part 2 */ | |
/* PART 3 - Interactivity */ | |
// Step 4: Hover interaction | |
.on("mouseenter", function(d){ | |
$("#city").html(d.city); | |
$("#inches").html(d.snow); | |
}); | |
/* END Part 3 */ | |
/* PART 5 - Drawing the Axes */ | |
// Renders the yAxis once the chart is finished | |
// -- Moves it to the left 10 pixels so it doesn't overlap | |
chart.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(-10, 0)") | |
.call(yAxis); | |
// Appends the yAxis | |
chart.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(0," + (height + 10) + ")") | |
.call(xAxis); | |
// Adds yAxis title | |
chart.append("text") | |
.text("Snow Totals") | |
.attr("transform", "translate(-70, -20)"); | |
/* END Part 5 */ | |
} | |
$(function(){ | |
// On document load, call the render() function to load the graph | |
render(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment