|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<link rel=stylesheet type=text/css href="style.css"> |
|
<title>Clickable U.S. Map</title> |
|
</head> |
|
<body> |
|
|
|
<section> |
|
<div id="map"></div> |
|
<div id="lookup"></div> |
|
<div id="information"></div> |
|
</section> |
|
|
|
<script> |
|
// from: http://bl.ocks.org/mbostock/4090848 |
|
var width = 450, |
|
height = 300; |
|
|
|
var str_ordinal = function(n) { |
|
var suffix = 'th'; |
|
if ( (n - 11) % 100 == 0 || (n - 12) % 100 == 0 || (n - 13) % 100 == 0 ) { |
|
// ends with 11 or 12 or 13 |
|
suffix = 'th'; |
|
} else if ( (n - 1) % 10 == 0 ) { |
|
// ends with 1 |
|
suffix = 'st'; |
|
} else if ( (n - 2) % 10 == 0 ) { |
|
suffix = 'nd'; |
|
} else if ( (n - 3) % 10 == 0 ) { |
|
suffix = 'rd'; |
|
} |
|
return n + suffix; |
|
}; |
|
|
|
var add_info = function(p){ |
|
var this_state = p.STATE; |
|
d3.select("#information").html( |
|
'<h1>' + p.STATE + '</h1>' + |
|
'The ' + str_ordinal(p.ORDER_ADM) + ' state, joining' + |
|
' on ' + p.MONTH_ADM + ' ' + p.DAY_ADM + ', ' + p.YEAR_ADM |
|
); |
|
d3.selectAll("g.state").classed("highlight", |
|
function(dd) { return dd.properties.STATE == this_state ? true : false; }); |
|
d3.selectAll("li.state").classed("highlight", |
|
function(dd) { return dd.STATE == this_state ? true : false; }); |
|
}; |
|
|
|
//---------------------------------------------- The clickmap |
|
var clickmap = d3.select("#map").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
d3.json("us-states-100k-ungrouped.json", function(error, us) { |
|
if (error) return console.error(error); |
|
|
|
var projection = d3.geo.albersUsa() |
|
.scale(450) |
|
.translate([width / 2, height / 2]); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var states = clickmap.selectAll("g.state") |
|
.data(topojson.feature(us, us.objects.states).features |
|
.filter(function(d) { return d.properties.STATE_FIPS != '72'; }) |
|
) |
|
.enter().append("g") |
|
// Exclude Puerto Rico because at this scale it is just 1 point |
|
// and there will be a rendering error because there is no centroid. |
|
.attr("class", "state") |
|
.on("mouseover", function(d) { |
|
var this_state = d.properties.STATE; |
|
d3.selectAll("li.state").classed("falsehover", |
|
function(dd) { return dd.STATE == this_state ? true : false; }); |
|
}) |
|
.on("mouseout", function(d) { |
|
d3.selectAll("li.state").classed("falsehover", false); |
|
}) |
|
.on("click", function(d) { add_info(d.properties); }); |
|
|
|
states.append("path") |
|
.attr("d", path) |
|
.attr("id", function(d) { return d.properties.STATE; }) |
|
.on("mousedown", |
|
function(d){ |
|
d3.select("#" + d.properties.STATE).classed("click", true); |
|
}) |
|
.on("mouseup", |
|
function(d){ |
|
d3.select("#" + d.properties.STATE).classed("click", false); |
|
}); |
|
|
|
states.append("text") |
|
.attr("class", "label") |
|
.attr("x", function(d){ return path.centroid(d)[0]; }) |
|
.attr("y", function(d){ return path.centroid(d)[1]; }) |
|
.attr("dy", "5px") |
|
.attr("font-family", "Sans-Serif" ) |
|
.text(function(d){ |
|
return d.properties.ABBR; }) |
|
|
|
|
|
//---------------------------------------------- The lookup list (for accessibility) |
|
var lookups = d3.select("#lookup") |
|
.append("ul").selectAll("li") |
|
.data(topojson.feature(us, us.objects.states).features |
|
.map(function(f){ return f.properties; }) |
|
.filter(function(d) { return d.STATE_FIPS != '72'; }) |
|
.sort(function(a, b){ return a.STATE.localeCompare(b.STATE); })) |
|
.enter().append("li") |
|
.attr("class", "state") |
|
.text(function(d) { return d.ABBR; }) |
|
.on("mouseover", function(d) { |
|
var this_state = d.STATE; |
|
d3.selectAll("g.state").classed("falsehover", |
|
function(dd) { |
|
return dd.properties.STATE == this_state ? true : false; }); |
|
}) |
|
.on("mouseout", function(d) { |
|
d3.selectAll("g.state").classed("falsehover", false); |
|
}) |
|
.on("click", add_info); |
|
|
|
|
|
// Pre-fill the info window with Delaware, the first state |
|
add_info(states.filter( |
|
function(d) { return d.properties.STATE_FIPS == 10; }).datum().properties); |
|
}); |
|
</script> |
|
</body> |
|
</html> |