Geodata - xerocrypt/Misc GitHub Wiki
In this repository:
- Offline Maps Demo
Uses:
- jQuery
- Leaflet.js
- Mobile Atlas Creator
Using the Leaflet.js API, HTML5 and CSS3, it is possible to create an offline map application that functions entirely independent of a working data connection.
Creating the Offline Map Files
The first thing we need is data, in the form of map tiles, and the easiest way of getting this is by generating them using the Mobile Atlas Creator. This is straightforward to use – simply select the region to map and the zoom levels the application would display (e.g. all of them), and create the atlas .zip archive. The archive contains sets of numbered directories and files – I’ll explain why they’re structured that way and how they’re read by the application. For the data source, ‘OpenStreetMap Public Transport‘ gave the clearest tile images.
Leaflet.js API
There are multiple JavaScript APIs for rendering maps in the browser and showing the current GPS position. I went with Leaflet.js, as it’s lightweight, functional and reasonably well-documented. This is roughly how Leaflet.js does the rendering: Leaflet.js will select the images to display according to the co-ordinates set in the code. The API will translate the co-ordinates into two five-digit numbers to select the file paths of the tiles to display. There is a third variable, which is the zoom level and layer – this determines the root directory that Leaflet.js will fetch the tiles from.
The three aforementioned factors are variables, z, x and y in the code. These correspond to the zoom level, latitude and longitude. All three are initially determined by the setview() parameters – the default zoom level and initial map frame displayed, but they’re changed by the JavaScript controls as the user scrolls and zooms in and out.
Geolocation
Leaflet.js includes a feature that makes use of the browser’s geolocation API. We include a button with this event trigger:
onClick="javascript:getLocationLeaflet();"
Which calls this function:
function getLocationLeaflet()
{
map.on('locationfound', onLocationFound);
map.on('locationerror', onLocationError);
map.locate({setView: true, maxZoom: 16});
}
Which, in turn, calls this function if the current location can be read from the device:
function onLocationFound(e)
{
var radius = e.accuracy / 2;
var location = e.latlng
L.marker(location).addTo(map)
L.circle(location, radius).addTo(map);
}
Of course, there’s no map in the screenshot here, as there aren’t any tiles for that location.
Location Markers
Another feature essential to my application is the ability to mark important locations on the map and display information about them. In this example, the placemark locations and popup messages are hard-coded into the JavaScript, though it should be possible to load that information from a GeoJSON file without having to use something like Node.js (I’m still working on this).
With the markers, the init() function should look something like this:
function init() {
map = new L.Map('map');
L.tileLayer('maps/kyoto-atlas/kyoto/{z}/{x}/{y}.png', { maxZoom: 15 })
.addTo(map);
map.setView(new L.LatLng(34.98852, 135.764982), 16);
L.marker([34.967169, 135.772437]).addTo(map)
.bindPopup('Fushimi Inari Shrine')
.closePopup();
L.marker([35.016917, 135.782388]).addTo(map)
.bindPopup('Heian Shrine')
.closePopup();
L.marker([34.985985, 135.741648]).addTo(map)
.bindPopup('Kyoto Railway Museum')
.closePopup();
}
Don’t forget there is always the CSS file included with Leaflet.js.
It shouldn’t matter whether the map files are replaced with something better from the Mobile Atlas Creator, as the co-ordinates within the JavaScript will always be mapped to the correct places.
To minimise the download size, I’ve published this example on GitHub with map tiles for only one zoom level, but it’s easy to recreate what I’ve done in the Mobile Atlas Creator.