Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save montanaflynn/0ee8c8e653f537367c7d44dd056de289 to your computer and use it in GitHub Desktop.
Save montanaflynn/0ee8c8e653f537367c7d44dd056de289 to your computer and use it in GitHub Desktop.
Canadian Covid 19 Choropleth Map
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/queue.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.0.1/spin.min.js'></script>
<h1>Canadian Covid-19 Confirmed Cases</h1>
const w = 800;
const h = 600;
const canadaTopoJSON =
"https://gistcdn.githack.com/montanaflynn/32f882ec77b0dd15bced6a28fad80028/raw/13f1fb4d257ca2f11dd441003ce578a46ec5097f/canada-provinces.topo.json";
const canadaDataJSON =
"https://montanaflynn.github.io/covid-19/data/current.json";
const canadaProjection = d3
.geoAzimuthalEqualArea()
.rotate([100, -45])
.center([5, 20])
.scale(w)
.translate([w / 2, h / 2]);
const canadaPaths = d3.geoPath().projection(canadaProjection);
d3.select("body")
.append("div")
.attr("class", "container");
var targets = document.getElementsByClassName("container")
var spinner = new Spinner().spin(targets[0]);
function loaded(error, topo, data) {
if (error) throw error;
spinner.stop();
const provinceGeo = topo.objects.provinces.geometries;
provinceGeo.forEach(function(geo, i) {
const provinceName = geo.properties.name;
if (provinceName in data.canada) {
provinceGeo[i].properties.confirmed = data.canada[provinceName].confirmed;
} else {
provinceGeo[i].properties.confirmed = 0;
}
});
const values = d3.entries(topo.objects.provinces.geometries).map(function(d) {
return d.value.properties.confirmed;
});
const totalCases = values.reduce(function getSum(total, num) {
return total + num;
});
console.log(totalCases);
const totalCasesHTML = "<b>Canada</b><br/>Confirmed Cases: " + totalCases;
const minVal = d3.min(values);
const maxVal = d3.max(values);
const color = d3
.scaleLinear()
.domain([minVal, 1, maxVal])
.range(["#eee", "#fee", "#f00"]);
var tooltip = d3
.select(".container")
.append("div")
.attr("class", "toolTip")
.html(totalCasesHTML);
const provinces = topojson.feature(topo, topo.objects.provinces);
const svg = d3
.select(".container")
.append("svg")
.attr("class", "canada")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("class", "provinces")
.selectAll("path")
.data(provinces.features)
.enter()
.append("path")
.attr("stroke", "#000")
.attr("stroke-width", 0.5)
.attr("fill", function(d, i) {
return color(d.properties.confirmed);
})
.attr("d", canadaPaths)
.on("mouseover", function(d) {
var currentState = this;
d3.select(this).style("stroke-width", 1.5);
tooltip
.style("display", "inline-block")
.html(
"<b>" +
d.properties.name +
"</b><br/>Confirmed Cases: " +
d.properties.confirmed
);
})
.on("mouseout", function(d) {
d3.select(this).style("stroke-width", 0.5);
tooltip.html(totalCasesHTML);
});
// add a legend
var legendDimensions = {
w: 300,
h: 50
};
var key = d3
.select(".container")
.append("svg")
.attr("width", legendDimensions.w + 10)
.attr("height", legendDimensions.h)
.attr("class", "legend");
var legend = key
.append("defs")
.append("svg:linearGradient")
.attr("id", "gradient")
.attr("y1", "100%")
.attr("x1", "0%")
.attr("y2", "100%")
.attr("x2", "100%")
.attr("spreadMethod", "pad");
legend
.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#f00")
.attr("stop-opacity", 1);
legend
.append("stop")
.attr("offset", "100%")
.attr("stop-color", "#eee")
.attr("stop-opacity", 1);
key
.append("rect")
.attr("width", legendDimensions.w)
.attr("height", legendDimensions.h)
.style("fill", "url(#gradient)")
.attr("transform", "translate(0,10)");
var x = d3
.scaleLinear()
.range([legendDimensions.w, 0])
.domain([minVal, maxVal]);
var yAxis = d3.axisBottom(x);
key
.append("g")
.attr("class", "y_axis")
.attr("transform", "translate(0,10)")
.call(yAxis);
}
d3.queue()
.defer(d3.json, canadaTopoJSON)
.defer(d3.json, canadaDataJSON)
.await(loaded);
html, body {
margin: 10px;
}
.container {
width: 840px;
height: 640px;
position: absolute;
}
.canada path {
cursor: crosshair
}
.toolTip {
position: absolute;
top: 0;
left: 0;
}
.legend {
position: absolute;
top: -10px;
right: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment