Before we draw the airports, we manipulate the airport locations data. We create an array holding one GeoJSON point geometry object per airport:
var airportLocation = [];
airports.forEach(function(el) {
var obj = {};
obj.type = 'Feature';
obj.id = el.iata;
obj.geometry = {
type: 'Point',
coordinates: [+el.long, +el.lat]
};
obj.properties = {};
airportLocation.push(obj);
});
airportMap = d3.map(airportLocation, function(d) { return d.id; });
Then we fill the global airportMap variable with a map we produce with d3.map(). d3.map() is a utility function that takes an array of objects to produce key-value pairs we can access with its own map.get() method. We won't use the map immediately but will get to it in a moment.
Every time we call the ready() function, that is every time the user presses a new button, we will redraw airports and the world. Both are drawn on the same canvas. If we want to change one thing on a canvas, we need to change everything on a canvas. There are ways to only update regions with clip-paths but with complex animations of multiple elements, this can become a mess real quick. So we erase and rebuild:
contextWorld.clearRect(0, 0, width, height);
drawMap(countries);
drawAirports(airportLocation);
Note, we're on the first canvas we've drawn – accessible via contextWorld. We've seen drawMap() a few paragraphs ago, drawAirports() is even simpler and speaks for itself:
function drawAirports(airports) {
airports.forEach(function(el,i) {
contextWorld.beginPath();
pathCanvas(el);
contextWorld.fillStyle = '#fff';
contextWorld.fill();
});
}
That's it. This background scene will be drawn with every button press updating the airports shown.