Swiftmap makes it easy to add raster tiles to the background of a map.
This demo is based on the map in “On Delhi’s outskirts, schools urgently need teachers”, published on 7 August, 2017 in the Hindustan Times. Map tiles by Carto.
See also:
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
font-family: "Helvetica Neue", sans-serif;
}
#legend {
position: absolute;
background: rgba(255, 255, 255, .8);
padding: 10px;
}
#map {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="legend">
<b>Select</b><br />
<input type="radio" name="property" value="students" checked /> Total students<br />
<input type="radio" name="property" value="student_teacher_ratio" /> Students per teacher
</div>
<div id="map"></div>
<!-- To load data, we use modules for d3-request & d3-queue -->
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script src="https://d3js.org/d3-request.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://unpkg.com/swiftmap@0.2.4/dist/swiftmap.min.js"></script>
<script>
// Create the map.
var map = swiftmap.map("#map");
// Set up a scheme for each visual property.
var schemeRadius = swiftmap.schemeContinuous()
.from(d => +d.students)
.to([1, 20]);
var schemeFill = swiftmap.schemeCategorical()
.from(d => d.most_urgent)
.to({
"TRUE": "#e74c3c",
"FALSE": "rgb(119, 119, 119)"
});
var schemeStroke = swiftmap.schemeCategorical()
.from(d => d.most_urgent)
.to({
"TRUE": "rgb(191, 39, 24)",
"FALSE": "rgb(51, 51, 51)"
});
var schemeOpacity = swiftmap.schemeCategorical()
.from(d => d.most_urgent)
.to({
"TRUE": .9,
"FALSE": .4
});
d3.queue()
.defer(d3.json, "delhi_1997-2012_district.json") // polygons data
.defer(d3.json, "new_schools.json") // points data
.defer(d3.csv, "schools.csv") // tabular data
.await(ready);
function ready(error, districts, schools, data){
// Add data to each scheme.
schemeRadius.data(data, d => +d.edudel_code);
schemeFill.data(data, d => +d.edudel_code);
schemeStroke.data(data, d => +d.edudel_code);
schemeOpacity.data(data, d => +d.edudel_code);
// Add tiles and geospatial data to your map.
// Then draw the polygons and bubbles.
map
.tiles("cartoLight")
.layerPolygons(districts)
.fit()
.drawBoundary()
.layerPoints(schools, d => +d.properties.edudel_code)
.drawPoints();
// Add the schemes to the bubbles for styling.
map.layers[1].points
.attr("r", schemeRadius)
.style("fill", schemeFill)
.style("stroke", schemeStroke)
.style("opacity", schemeOpacity);
// Update the points' radii when the radio input changes.
var inputs = document.getElementsByName("property");
for (var i = 0, l = inputs.length; i < l; i++) {
inputs[i].onchange = function() {
schemeRadius.from(d => +d[this.value]);
map.layers[1].points.transition().duration(1500).attr("r", schemeRadius);
}
}
// It's easy to resize a Swiftmap.
window.onresize = () => map.resize();
}
</script>
</body>
</html>