JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<head>
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.1/tinycolor.js"></script>
<title>Unemployment rates in the United States, 2020</title>
</head>
<body>
<div class="home"></div>
</body>
<script>
Number.prototype.round = function (decimals) {
return Number((Math.round(this + "e" + decimals) + "e-" + decimals));
};
function selectDivisionNumber(array) {
let arraySize = array.length,
halfArray = Math.round(arraySize / 2);
let newArr = [];
//Take first and last item and push them to the array
newArr.push(array[0])
newArr.push(array[arraySize - 1]);
//Don't mind the order, they will be sorted later.
//Divide the array in two
let firstHalf = array.slice(0, halfArray);
let firstHalfSelection = firstHalf[Math.round(firstHalf.length / 2)];
newArr.push(firstHalfSelection);
let secondHalf = array.slice(halfArray, arraySize);
let secondHalfSelection = secondHalf[Math.round(secondHalf.length / 2)];
newArr.push(secondHalfSelection);
return newArr;
}
</script>
CSS
body {
height: 100vh;
font-family: "Open Sans", sans-serif;
}
.state {
stroke-width: 1;
stroke: #ffffff;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
min-height: 28px;
padding: 8px 12px;
font: 12px sans-serif;
background: lightgray;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
JavaScript
let fetchData = async () => {
//I've handily uploaded the data to this site for easy reference.
let url = "https://api.myjson.com/bins/cgbm8";
//'fetch()' returns a promise
let response= await fetch(url);
//'json()' also returns a promise
return response.json();
};
const width = 800;
const height = 563;
const svg = d3.select(".home").append("svg")
.attr("width", width)
.attr("height", height);
const projection = d3.geoAlbersUsa()
.translate([width / 2, height / 2]) // translate to center of screen
.scale([1000]); // scale things down so see entire US
const path = d3.geoPath().projection(projection);
fetchData().then(response => {
const tooltip = d3.select(".home").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
let sampleMap = response.data.map(item => {
return Number(item.unemploymentRate);
});
let domain = selectDivisionNumber(sampleMap).sort();
//To help generate the scale, https://hihayk.github.io/scale/
const colorScale = d3.scaleLinear()
.domain(domain)
.range(["#00806D", "#00BC4C", "#00F200", "#85FB44"].reverse());
d3.json("https://gist.githubusercontent.com/Bradleykingz/3aa5206b6819a3c38b5d73cb814ed470/raw/a476b9098ba0244718b496697c5b350460d32f99/us-states.json", function (error, uState) {
if (error) throw error;
_(uState.features)
.keyBy('properties.name')
.merge(_.keyBy(response.data, 'State'))
.values()
.value();
svg.selectAll('path')
.data(uState.features)
.enter()
.append('path')
.attr("d", path)
.style('transition', "all 0.2s ease-in-out")
.attr('class', 'state')
.style('fill', function...