This example shows a choropleth map of Connecticut, showing the town subdivisions. The example resizes the map to use the space available, while still keeping the correct aspect ratio.
This visualization is part of a series focused on Run 169. I'm trying to run a road race in each of Connecticut's 169 towns. Green shows that I have already run a race in that town. Hover over a town to see its name and driving time from my town.
To experience the resize behavior, run this example full-screen and resize the browser.
Notes:
forked from curran's block: Responding to Resize
Choropleth map code based on this video
Other data
Used topojson to convert large GeoJSON to TopoJSON and then simplify the shapes. Note that TopoJSON includes topology information, so when the shapes in the map are simplified (for speed) common boundaries between towns remain as common boundaries. In contrast, simplifying GeoJSON files creates gaps.
forked from jpasini's block: [unlisted] Resizable choropleth map
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<title>Dynamic Size Example</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<style>
/* Make the chart container fill the page using CSS. */
#chart {
position: fixed;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
.area {
stroke: #fff;
stroke-width: 1.5px;
opacity: 0.7;
fill: #aaa;
}
.area:hover {
opacity: 1.0;
}
.alreadyRun {
fill: darkgreen;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
const chartDiv = document.getElementById("chart");
const svg = d3.select(chartDiv).append("svg");
const scaleColor = d3.scaleLinear();
function getMapScale(width, height) {
// known size of CT image for given scale
const baseScale = 12000;
const baseWidth = 453;
const baseHeight = 379;
const scale1 = baseScale*width/baseWidth;
const scale2 = baseScale*height/baseHeight;
return d3.min([scale1, scale2]);
}
const drivingTimesMap = {};
build_driving_map = row => {
drivingTimesMap[row.Town] = {};
drivingTimesMap[row.Town].time = +row.DrivingTime;
const hours = Math.floor(+row.DrivingTime/60);
const mins = +row.DrivingTime - 60*hours;
if(hours > 0) {
drivingTimesMap[row.Town].timeString = hours + "h " + mins + " min";
} else {
drivingTimesMap[row.Town].timeString = mins + " min";
}
return row;
};
const racesRunMap = {};
build_races_run_map = row => {
racesRunMap[row.Town] = {};
racesRunMap[row.Town].distance = row.Distance;
return row;
};
function dataLoaded(error, mapData, drivingTimes, racesRun){
function redraw(){
// Extract the width and height that was computed by CSS.
const width = chartDiv.clientWidth;
const height = chartDiv.clientHeight;
const centerX = width/2;
const centerY = height/2;
// Use the extracted size to set the size of an SVG element.
svg
.attr("width", width)
.attr("height", height);
// Start work on the choropleth map
// idea from https://www.youtube.com/watch?v=lJgEx_yb4u0&t=23s
const mapScale = getMapScale(width, height);
const CT_coords = [-72.7,41.6032];
const projection = d3.geoMercator()
.center(CT_coords)
.scale(mapScale)
.translate([centerX, centerY]);
const path = d3.geoPath().projection(projection);
const group = svg.selectAll("g")
//.data(mapData.features);
.data(topojson.feature(mapData, mapData.objects.townct_37800_0000_2010_s100_census_1_shp_wgs84).features);
const areas = group
.enter()
.append("g").append("path")
.attr("d", path)
.attr("class", d => d.properties.NAME10 in racesRunMap ? "area alreadyRun" : "area")
.attr("fill", "steelblue")
.append("title")
.text(d => d.properties.NAME10 + ": " + drivingTimesMap[d.properties.NAME10].timeString);
areas.merge(group).selectAll("path")
.attr("d", path);
}
// Draw for the first time to initialize.
redraw();
// Redraw based on the new size whenever the browser window is resized.
window.addEventListener("resize", redraw);
}
d3.queue()
.defer(d3.json, "ct_towns_simplified.topojson")
.defer(d3.csv, "driving_times_from_avon.csv", build_driving_map)
.defer(d3.csv, "towns_run.csv", build_races_run_map)
.await(dataLoaded);
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v2.min.js