Published
- 3 min read
Leaflet fog of war
When I was playing age of empires the map was all in black color at the beginning. As long as you explore the map, the black color is removed discovering what it was hidden behind.
I wanted to implement something similar to show all the trails, routes, paths, roads, streets, etc that I have discovered. I’ll describe the callenges I have found in a series of articles.
This is part of my series of articles about leaflet:
- Leaflet fog of war
- Draw a polygon from markers in leaflet
- Load and display GPX in leaflet
- Browser storage
Age of empires… what a great game
I want to create something similar to the map in Age of Empires. A map where everything is hidden until you discovered. This way you could check how much of your city you know, or where to search for new places to visit.
I have worked many times before with leaflet js, a nice library to display maps and geographic information. It has a nice ecosystem of plugins, so I’ve checked if someone has something similar implemented and YES!
Leaflet.Mask already implemented a plugin that mask all the map and displays the area specified in the begining.
However, it does not fit my requirements as I want to add places dynamically. So, let’s implement our own thing …
Implementing my own Leaflet Mask
Taking Leaflet.Mask as a base, I will modify it a bit in order to be able to add the visited area dynamically.
The key for this to succeed was to understand how the polygon has to be created in leaflet:
scotland = L.polygon([
[
[60, -13],
[60, 0],
[50, 4],
[50, -13]
],
[
[55.7, -4.5],
[56, -4.5],
[56, -4],
[55.7, -4]
]
])
scotland.addTo(map)
In order to draw the polygon, the user might pass the list of latitude longitudes and a second optional argument that defines the holes of that polygon.
Finally the code looked something similar to:
_setMaskLayer: function () {
if (this.masklayer) {
this.removeLayer(this.masklayer)
}
var allWorld = this._coordsToLatLngs(this._allWorldCoordinates)
var latlngs = [allWorld]
this._holes.forEach((hole) => latlngs.push(this._coordsToLatLngs(hole)))
var layer = new L.Polygon(latlngs, this.options);
this.masklayer = layer
this.addLayer(layer);
},
The plugin reads the input data as GeoJSON and store the visited places latitude and longitude in the this._holes
variable. Later on, this array is iterated in order to build the holes that leaflet will draw into the polygon. Finally the created polygon is added to the map. When the method is called, the polygon is removed to be able to redraw it.
Here you can see it in action: https://www.agalera.eu/leaflet-fogofwar/
But wait … that’s not all, I want the fulfill the following requirements:
- I need a way to draw the areas I visisted, covered in the article: Draw a polygon from markers in leaflet
- Load a GPX and display it in the map, covered in the article: Load and display GPX in leaflet
- I don’t want to spent any money in this, so the storage will be browser based. This is covered in the article: Browser storage