|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Neighboring Geography Selection</title> |
|
<style> |
|
|
|
body { |
|
font: 9px sans-serif; |
|
} |
|
|
|
.county { |
|
stroke: slategrey; |
|
stroke-width: 1px; |
|
} |
|
|
|
.bar { |
|
stroke: lightgrey; |
|
stroke-width: .5px; |
|
} |
|
.q-0 { fill: #f7f7f7; } |
|
.q-1 { fill: #d9d9d9; } |
|
.q-2 { fill: #bdbdbd; } |
|
.q-3 { fill: #969696; } |
|
.q-4 { fill: #636363; } |
|
.q-5 { fill: #252525; } |
|
|
|
.hovered { |
|
webkit-transition: 250ms; |
|
-moz-transition: 250ms; |
|
-o-transition: 250ms; |
|
transition: 250ms; |
|
fill: red; |
|
font-weight: bold; |
|
} |
|
|
|
.neighbor { |
|
webkit-transition: 250ms; |
|
-moz-transition: 250ms; |
|
-o-transition: 250ms; |
|
transition: 250ms; |
|
fill: rgb(255, 129, 129); |
|
font-weight: bold; |
|
} |
|
|
|
.axis line { |
|
fill: none; |
|
stroke: #000; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.axis path { |
|
display: none; |
|
} |
|
|
|
svg { |
|
position: absolute; |
|
} |
|
|
|
.map { |
|
left: 300px; |
|
} |
|
|
|
</style> |
|
</head> |
|
<body> |
|
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script> |
|
<script> |
|
var margin = {top: 10, left: 70, bottom: 40, right: 20}, |
|
width = 960/2 - margin.left - margin.right, |
|
height = 700 - margin.top - margin.bottom; |
|
|
|
var projection = d3.geo.conicConformal() |
|
.rotate([90, 0]) |
|
.center([.2, 44.75]) |
|
.parallels([29.5, 45.5]) |
|
.scale(6000) |
|
.translate([ |
|
(width + margin.left + margin.right) / 2, |
|
(height + margin.top + margin.bottom) / 2 |
|
]) |
|
.precision(.1); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var scale = { |
|
x: d3.scale.linear().range([0, width]), |
|
y: d3.scale.ordinal().rangeBands([height, 0], .1), |
|
color: d3.scale.quantize() |
|
.range(d3.range(6)) |
|
}; |
|
|
|
var axis = { |
|
x: d3.svg.axis().scale(scale.x).orient("bottom"), |
|
y: d3.svg.axis().scale(scale.y).orient("left") |
|
}; |
|
|
|
var chart = d3.select("body").append("svg") |
|
.attr("class", "chart") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
var map = d3.select("body").append("svg") |
|
.attr("class", "map") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom); |
|
|
|
chart.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")"); |
|
|
|
chart.append("g") |
|
.attr("class", "y axis"); |
|
|
|
d3.json("wi.json", ready) |
|
|
|
function ready(error, wi) { |
|
if (error) throw error; |
|
|
|
var countyData = cleanData(wi); |
|
|
|
scale.x.domain([0, d3.max(countyData, function(d) { return d.unemployment_rate; })]); |
|
scale.y.domain(countyData.map(function(d) { return d.name; })); |
|
scale.color.domain(d3.extent(countyData, function(d) { return d.unemployment_rate; })); |
|
|
|
// Draw map |
|
var counties = map.selectAll(".county").data(countyData) |
|
.enter().append("path") |
|
.attr("class", function(d) { return "county q-" + scale.color(d.unemployment_rate); }) |
|
.attr("d", path) |
|
.on("mouseenter", mouseenter) |
|
.on("mouseleave", mouseleave); |
|
|
|
// Draw bar chart |
|
var bars = chart.selectAll(".bar").data(countyData) |
|
.enter().append("rect") |
|
.attr("x", function(d) { return scale.x(0); }) |
|
.attr("y", function(d) { return scale.y(d.name); }) |
|
.attr("width", function(d) { return scale.x(d.unemployment_rate); }) |
|
.attr("height", function(d) { return scale.y.rangeBand(); }) |
|
.attr("class", function(d) { return "bar q-" + scale.color(d.unemployment_rate); }) |
|
.on("mouseenter", mouseenter) |
|
.on("mouseleave", mouseleave); |
|
|
|
|
|
var labels = chart.selectAll(".label").data(countyData) |
|
.enter().append("text") |
|
.attr("x", function(d) { return scale.x(d.unemployment_rate); }) |
|
.attr("y", function(d) { return scale.y(d.name); }) |
|
.attr("dx", 3) |
|
.attr("dy", 7) |
|
.style("text-anchor", "start") |
|
.text(function(d) { return d.unemployment_rate; }); |
|
|
|
|
|
chart.select(".x.axis") |
|
.call(axis.x) |
|
.append("text") |
|
.attr("x", width) |
|
.attr("y", 30) |
|
.style("text-anchor", "end") |
|
.text("Unemployment Rate (%)"); |
|
|
|
chart.select(".y.axis") |
|
.call(axis.y); |
|
|
|
function mouseenter(hovered) { |
|
counties |
|
.classed("hovered", function(d) { return d === hovered; }) |
|
.classed("neighbor", function(d) { return hovered.neighbors.indexOf(d) !== -1; }); |
|
|
|
bars |
|
.classed("hovered", function(d) { return d === hovered; }) |
|
.classed("neighbor", function(d) { return hovered.neighbors.indexOf(d) !== -1; }); |
|
|
|
labels |
|
.classed("hovered", function(d) { return d === hovered; }) |
|
.classed("neighbor", function(d) { return hovered.neighbors.indexOf(d) !== -1; }); |
|
|
|
chart.select(".y.axis").selectAll("g") |
|
.classed("hovered", function(name) { return name === hovered.name; }) |
|
.classed("neighbor", function(name) { |
|
return hovered.neighbors |
|
.filter(function(d) { return d.name === name; }).length > 0; |
|
}); |
|
} |
|
|
|
function mouseleave() { |
|
counties |
|
.classed("hovered", false) |
|
.classed("neighbor", false); |
|
|
|
bars |
|
.classed("hovered", false) |
|
.classed("neighbor", false); |
|
|
|
labels |
|
.classed("hovered", false) |
|
.classed("neighbor", false); |
|
|
|
chart.select(".y.axis").selectAll("g") |
|
.classed("hovered", false) |
|
.classed("neighbor", false); |
|
} |
|
} |
|
|
|
function cleanData(wi) { |
|
var features = topojson.feature(wi, wi.objects.wi).features, |
|
neighbors = topojson.neighbors(wi.objects.wi.geometries), |
|
countyData = features |
|
.map(function(d,i) { |
|
d.neighbors = features.filter(function(d1, i1) { |
|
return neighbors[i].indexOf(i1) !== -1; |
|
}); |
|
d.unemployment_rate = +d.properties["wi-data__2"]; |
|
d.name = d.properties.NAME; |
|
return d; |
|
}) |
|
.sort(function(a, b) { |
|
return b.unemployment_rate - a.unemployment_rate; |
|
}); |
|
|
|
return countyData; |
|
} |
|
|
|
d3.select(self.frameElement) |
|
.style("width", 800 + "px") |
|
.style("height", (height + margin.top + margin.bottom) + "px"); |
|
</script> |
|
</body> |
|
</html> |