Skip to content

Instantly share code, notes, and snippets.

@fhernand
Last active August 29, 2015 14:06
Show Gist options
  • Save fhernand/be1e9c9fdb0473292abf to your computer and use it in GitHub Desktop.
Save fhernand/be1e9c9fdb0473292abf to your computer and use it in GitHub Desktop.
Choropleth with svg filter

Based on Mike Bostock's example for a choropleth map and merging states II map

Merges features based on quantized employment level. Adds an svg filter to each merged features level. It also builds the features layer by layer to ensure that shadows seem consistent.

Looks nice, but quite slow to load due to the filters.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.counties {
fill: none;
stroke: none;
}
.states {
fill: none;
stroke-width: 0.2;
stroke: rgb(8,48,107);
stroke-linejoin: round;
}
.q0-9 { fill:rgb(247,251,255);
stroke-width: 0.2;
stroke: rgb(222,235,247);
stroke-linejoin: round;}
.q1-9 { fill:rgb(222,235,247);
stroke-width: 0.2;
stroke: rgb(198,219,239);
stroke-linejoin: round;}
.q2-9 { fill:rgb(198,219,239);
stroke-width: 0.2;
stroke: rgb(158,202,225);
stroke-linejoin: round;}
.q3-9 { fill:rgb(158,202,225);
stroke-width: 0.2;
stroke: rgb(107,174,214);
stroke-linejoin: round;}
.q4-9 { fill:rgb(107,174,214);
stroke-width: 0.2;
stroke: rgb(66,146,198);
stroke-linejoin: round;}
.q5-9 { fill:rgb(66,146,198);
stroke-width: 0.2;
stroke: rgb(33,113,181);
stroke-linejoin: round;}
.q6-9 { fill:rgb(33,113,181);
stroke-width: 0.2;
stroke: rgb(8,81,156);
stroke-linejoin: round;}
.q7-9 { fill:rgb(8,81,156);
stroke-width: 0.2;
stroke: rgb(8,48,107);
stroke-linejoin: round;}
.q8-9 { fill:rgb(8,48,107);
stroke-width: 0.2;
stroke: rgb(8,48,107);
stroke-linejoin: round;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<svg class="svg1" width="960px" height="600px" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="f3" x="-0.1" y="-0.1" width="400%" height="400%">
<feOffset result="offOut" in="SourceAlpha" dx="1" dy="1"></feOffset>
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="1"></feGaussianBlur>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
</filter>
</defs>
</svg>
<script>
var width = 960,
height = 600;
var rateById = d3.map();
var quantize = d3.scale.quantize()
.domain([0, .15])
.range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
var projection = d3.geo.albersUsa()
.scale(1280)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select(".svg1");
queue()
.defer(d3.json, "/mbostock/raw/4090846/us.json")
.defer(d3.tsv, "/mbostock/raw/4060606/unemployment.tsv", function(d) { rateById.set(d.id, +d.rate); })
.await(ready);
function ready(error, us) {
var counties = topojson.feature(us, us.objects.counties),
selection0 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q0-9"; })},
selection1 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q1-9"; })},
selection2 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q2-9"; })},
selection3 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q3-9"; })},
selection4 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q4-9"; })},
selection5 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q5-9"; })},
selection6 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q6-9"; })},
selection7 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q7-9"; })},
selection8 = {type: "FeatureCollection", features: counties.features.filter(function(d) { return quantize(rateById.get(d.id)) == "q8-9"; })};
svg.append("path")
.datum(selection0)
.attr("class", "q0-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection1)
.attr("class", "q1-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection2)
.attr("class", "q2-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection3)
.attr("class", "q3-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection4)
.attr("class", "q4-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection5)
.attr("class", "q5-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection6)
.attr("class", "q6-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection7)
.attr("class", "q7-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(selection8)
.attr("class", "q8-9")
.attr("d", path)
.attr("filter","url(#f3)");
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
}
d3.select(self.frameElement).style("height", height + "px");
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment