index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Core Housing Need in Canada</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,700,300italic' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
margin: 0;
background-color: #fff;
font-family: Helvetica,Arial,sans-serif;
}
#container {
max-width: 700px;
position: relative;
margin-left: 20px;
margin-right: auto;
margin-top: 20px;
padding: 10px 50px;
background-color: #fff;
box-shadow: 2px 2px 2px 2px #ccc;
}
#chartbox {
max-width: 650px;
position: absolute;
top: 20px;
left: 850px;
padding: 10px;
box-shadow: 2px 2px 2px 2px #ccc;
}
#mapBox {
max-width: 650px;
position: absolute;
top: 20px;
left: 1230px;
padding: 10px;
box-shadow: 2px 2px 2px 2px #ccc;
}
p {
font-size: 16px;
color: #4e5a64;
margin: 15px 0 50px;
}
h1 {
font-weight: 700;
color: #4e5a64;
font-size: 32px;
}
h2 {
font-weight: 500;
color: #4e5a64;
font-size: 22px;
}
a:link {
text-decortion: none;
color: gray;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: gray;
}
a:active {
color: #87ceeb;
}
svg {
background-color: #fff;
}
g.bar text {
font-size: 14px;
font-weight: 550;
text-anchor: end;
opacity: 0;
fill: #fff;
stroke: none;
}
g.bar:hover text {
opacity: 1;
}
.axis path,.axis line {
fill: none;
stroke: #4e5a64;
}
.axis text {
font-family: sans-serif;
font-size: 12px;
fill: #4e5a64;
stroke: none;
}
.y.axis path,.y.axis line {
opacity: 0;
}
path { stroke:#fff ;
stroke-width: .9px;
fill: #BDD684;
}
path:hover{
fill: #5e6b42;
}
#mapBox {
background-color: white;
margin: auto;
max-width: 800px;
}
.header,
.info,
{
margin: auto;
max-width: 800px;
}
#tooltip {
z-index: 1;
position: absolute;
width: auto;
height: auto;
padding: 6px;
background-color: white;
opacity: 1;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: 'Open Sans Condensed', sans-serif;
font-size: 1em;
line-height: 1;
}
</style>
</head>
<body>
<div id="container">
<h1>Core Housing Need in Canada - Part 1</h1>
<p>A household is said to be in core housing need if its housing falls
below at least one of the adequacy, affordability or suitability,
standards and it would have to spend 30% or more of its total
before-tax income to pay the median rent of alternative local housing
that is acceptable (meets all three housing standards).<br>
- Adequate housing are reported by their residents as not requiring any
major repairs.<br>
- Affordable dwellings costs less than 30% of total before-tax
household income.<br>
- Suitable housing has enough bedrooms for the size and make-up of
resident households, according to National Occupancy Standard (NOS)
requirements.</p>
<h2>What do Canadians earn?</h2>
<p>Average Household Income ($) by Province and Territory - 2011<br>
Source: <a href="//cmhc.beyond2020.com/">Canada Mortgage and
Housing Corporation</a>, 2015</p>
</div>
<div id="chartbox">
<h1>Regional Profile</h1>
</div>
<div id="mapBox">
</div>
<script type="text/javascript">
var w = 650;
var h = 450;
var padding = [20, 10, 30, 220];
var widthScale = d3.scale.linear()
.range([0, w - padding[1] - padding[3]]);
var heightScale = d3.scale.ordinal()
.rangeBands([padding[1], h / 1.2 - padding[1]], 0.1);
var xAxis = d3.svg.axis()
.scale(widthScale)
.orient("bottom")
.ticks(7)
.tickFormat(d3.format("$,.0f"));
var yAxis = d3.svg.axis()
.scale(heightScale)
.orient("left");
var svg = d3.select("#container")
.append("svg")
.attr("width", w)
.attr("height", h);
var svg2 = d3.select("#chartbox")
.append("svg")
.attr("width", w / 2)
.attr("height", h * 1.5)
.attr("id", "redLine");
d3.csv("coreHousingNeed-prov-tert.csv", function(data)
{
data.sort(function(a, b){
return d3.descending(+a.Average_Household_Income, +b.Average_Household_Income);
});
widthScale.domain([0, d3.max(data, function(d){
return +d.Average_Household_Income;
})]);
heightScale.domain(data.map(function(d){
return d.Geography;
}));
var groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("class", "bar");
var group = svg2.selectAll("g")
.data(data)
.enter()
.append("g")
.on("click", function(){
var active = redLine.active ? false : true,
newOpacity = active ? 0 : 1;
d3.select("#redLine")
.transition()
.duration(2000)
.style("opacity", newOpacity);
redLine.active = active;
});
var rects = groups.append("rect")
.attr("x", padding[3])
.attr("id", "blueLine")
.attr("y", function(d){
return heightScale(d.Geography);
})
.attr("width", 0)
.attr("height", heightScale.rangeBand())
.on("click", function(d){
console.log(d);
})
.attr({
fill: function(d)
{
if (d.Average_Household_Income > 90000){
return "#FF0033";
}
else if (d.Average_Household_Income < 70000){
return "#CCCCFF";
}
else{
return "#33CCFF";
}
}
});
var numFormat = d3.format("$,");
groups.append("text")
.attr("x", function(d)
{
return padding[3] + widthScale(d.Average_Household_Income) -
3;
})
.attr("y", function(d)
{
return heightScale(d.Geography) + 17;
})
.text(function(d)
{
return "Average household income" + " " + numFormat(d.Average_Household_Income);
})
var weebox = group.append("circle")
.attr("r", 90)
.attr("cx", 100)
.attr("cy", 100)
.attr("fill", "#ffffff")
.transition()
.duration(5000)
.attr(
{
fill: function(d)
{
if (d.Average_STIR > 100)
{
return "#FF0033";
}
else
{
return "#bdd684";
}
}
})
.transition()
.duration(5000)
.attr("cx", 200)
.transition()
.duration(5000)
.attr("cx", 100);
var rects2 = group.select("circle")
.on("click", function(d){
window.alert("You clicked the circle and now it will vanish");
})
rects.transition()
.delay(function(d, i)
{
return i * 50;
})
.duration(1000)
.attr("width", function(d)
{
return widthScale(d.Average_Household_Income);
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + padding[3] + "," + (h / 1.11 -
padding[2]) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + padding[3] + ",0)")
.call(yAxis);
});
</script>
<script type="text/javascript">
var width = 800,
height =700,
centered;
var projection = d3.geo.albers()
.center([-3.5, 46.4])
.rotate([121,-11])
.scale(2600)
.translate([w / 2, h / 2]);
var path = d3.geo.path()
.projection(projection);
var svg3 = d3.select("#mapBox")
.append("svg")
.attr("width", w)
.attr("height", h * 1.5);
d3.json(src="https://gist.githubusercontent.com/majomo/1beba4e212d12f3d6e29/raw/1bd280591bc4959449505395c90f7ffdd2e2ddbd/bcGeo.json", function(json)
{
svg3.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.on("mousemove", function(d) {
var xPosition = parseFloat(d3.select(this).attr("cx"));
var yPosition = parseFloat(d3.select(this).attr("cy"));
var currentState = this;
d3.select(this).style('fill-opacity', 1);
d3.select("#tooltip")
.style("left", (d3.event.pageX+20) + "px")
.style("top", (d3.event.pageY ) + "px")
.select("#NAME")
.text(d.properties.CDNAME);
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout", function() {
d3.selectAll('path')
.style({
'fill-opacity':10});
d3.select("#tooltip").classed("hidden", true);
});
});
</script>
</body>
</html>
coreHousingNeed-prov-tert.csv
Geography,Year,Household_Count,Average_Household_Income,Average_Shelter_Cost,Average_STIR
NEWFOUNDLAND and LABRADOR,2011,201875,70936,754,18.3
PRINCE EDWARD ISLAND,2011,53620,68301,817,20.1
NOVA SCOTIA,2011,369760,69362,838,20.7
NEW BRUNSWICK,2011,298955,67122,757,19
QUEBEC,2011,3224260,68926,834,21.3
ONTARIO,2011,4600055,89873,1175,22.8
MANITOBA,2011,423200,74940,846,19.2
SASKATCHEWAN,2011,359375,81353,910,19.6
ALBERTA,2011,1285165,106241,1249,21.1
BRITISH COLUMBIA,2011,1610540,82674,1136,23.4
YUKON,2011,12950,92906,1084,19.2
NORTHWEST TERRITORIES,2011,14150,116039,1350,17.5
NUNAVUT,2011,8545,100417,852,11.1