This choropleth uses d3-scale-cluster to visualize unemployment rates from 2008, and allows quick comparison between the cluster scale and D3's built in quantile and quantize scales.
For more information on the clustering scale, read Using clustering to create a new D3.js color scale
xxxxxxxxxx
<meta charset="utf-8">
<style>
.container {
padding: 20px;
font-family: 'Helvetica Neue', Helvetica, sans-serif;
width: 960px;
max-width: 100%;
}
.counties {
fill: none;
}
.states {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
.q0-9 { fill:rgb(247,251,255); }
.q1-9 { fill:rgb(222,235,247); }
.q2-9 { fill:rgb(198,219,239); }
.q3-9 { fill:rgb(158,202,225); }
.q4-9 { fill:rgb(107,174,214); }
.q5-9 { fill:rgb(66,146,198); }
.q6-9 { fill:rgb(33,113,181); }
.q7-9 { fill:rgb(8,81,156); }
.q8-9 { fill:rgb(8,48,107); }
.tooltip {
background: #fff;
border: 1px solid #ddd;
position: absolute;
bottom: 0;
left: 0;
padding: 6px 7px;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
border-radius: 2px;
}
.button-label, .buttons {
display: inline-block;
vertical-align: middle;
}
.button-label {
font-size: 15px;
opacity: 0.6;
margin-right: 10px;
}
.button {
border: 1px solid #3498db;
padding: 7px 10px;
color: #2980b9;
display: inline-block;
vertical-align: middle;
cursor: pointer;
}
.button.selected, .button:hover {
background: #3498db;
color: #fff;
}
.button:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.button:last-child {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.button + .button {
border-left: 0;
}
.scales {
text-align: center;
}
</style>
<div class="container">
<div class="scales">
<div class="button-label">Select a scale:</div>
<div class="buttons">
<div class="button selected" data-type="cluster">Cluster</div><div class="button" data-type="quantile">Quantile</div><div class="button" data-type="quantize">Quantize</div>
</div>
</div>
<div style="position: relative;">
<svg width="960" height="600"></svg>
<div class="tooltip"></div>
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://unpkg.com/d3-scale-cluster@1.1.2/dist/d3-scale-cluster.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var tooltip = document.querySelector('.tooltip');
var rateById = d3.map();
var projection = d3.geoAlbersUsa()
.scale(1280)
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
d3.queue()
.defer(d3.json, "/../../data/us.json")
.defer(d3.tsv, "unemployment.tsv", function(d) { rateById.set(d.id, +d.rate); })
.await(ready);
var range = d3.range(9).map(function(i) { return "q" + i + "-9"; });
var values;
var scale;
function ready(error, us) {
if (error) throw error;
values = rateById.values();
// Start with cluster scale
scale = getScale('cluster');
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("class", function(d) { return 'county ' + scale(rateById.get(d.id)); })
.attr("d", path)
.on('mouseover', function(d){
// Bring to front and show stroke
this.parentNode.appendChild(this);
d3.select(this).attr('stroke', '#000');
// Update toolitp
tooltip.style.opacity = 1;
tooltip.innerHTML = rateById.get(d.id);
})
.on('mouseout', function(){
d3.select(this).attr('stroke', null);
tooltip.style.opacity = 0;
});
// Tooltip positioning
svg.on('mousemove', function(){
var mouse = d3.mouse(this);
tooltip.style.bottom = (600 - mouse[1] + 10) + 'px';
tooltip.style.left = (mouse[0] + 10) + 'px';
});
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
document.querySelectorAll('.button').forEach(function(e){
e.addEventListener('click', onScaleChange);
});
}
function renderWithScale(scale) {
svg.selectAll('.county').attr('class', function(d){
return 'county ' + scale(rateById.get(d.id));
});
}
function getScale(type) {
if (type === 'cluster') {
return d3.scaleCluster().domain(values).range(range);
} else if (type === 'quantile') {
return d3.scaleQuantile().domain(values).range(range);
} else if (type === 'quantize') {
return d3.scaleQuantize().domain(d3.extent(values)).range(range);
}
}
function onScaleChange() {
var el = this;
renderWithScale( getScale(el.dataset.type) );
Array.prototype.filter.call(el.parentNode.children, function(child){
if (child !== el) {
child.classList.remove('selected');
} else {
child.classList.add('selected');
}
});
};
</script>
Changed /mbostock/raw/4090846/us.json to a local referenece
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v1.min.js
https://unpkg.com/d3-scale-cluster@1.1.2/dist/d3-scale-cluster.min.js