Leaflet Maps - Saving the map state



Just a quick one today for leaflet maps...

Leaflet Maps

If you've not come across leaflet maps before it's a good alternative to Google maps; especially as the projects I'm currently working on are not public facing sites, which Google has decided it would like to have a chat about if you're wanting to use their API.

As a way round various licencing issues I'm using Leaflet Maps as the base mapping software, and Map Quest for the tiles. The combination gives me a fully open source mapping solution.

Anywho...

I won't go too much into the in's and out's of setting up leaflet maps, there's very good documentation to be found on the link above.

My basic setup is to give the user the option to click the map to add a marker for their location. This can then be dragged about to refine the location. Adding and moving the marker updates hidden input fields for latitude and longitude which are then saved to a database on a form submission. I've also used Nominatim's Open Street Map tool (also free to use within boundaries) to suggest a marker location based on postcode, but neither the available geocoding data, or address data, is necessarily good enough to rely on this alone.

This is all fine. The user can mark their location, adjust map position and zoom levels as they wish. What's recently been requested is however:

Can the map position and zoom be saved as I left it?

Yes. Is the short answer. Actually it's pretty simple. Saving the map state is really just a case of saving the bounds; the zoom level and map position is just determined by the latitude and longitude of the bounding box the map sits in.

Here's some code:

Firstly, all the logic for generating the map and associated functionality is inside a JavaScript object, which accepts an array of options as a parameter. A _renderMap() method handles the setup to display the map.

this.defaulZoom = 8;

this._renderMap = function()
{
    this.map = new L.Map('lmap');
    var streetTile = 'http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png';
    var mapQuestUrl = streetTile,
         mapQuestSubDomains = ['otile1','otile2','otile3','otile4'],
         mapQuestAttrib = 'Data, imagery and map information provided by MapQuest, OpenStreetMap  
           and contributors, CC-BY-SA  
           - Search powered by geonames.org';
 
    var mapQuest = new L.TileLayer(mapQuestUrl, {maxZoom: 18, attribution: mapQuestAttrib, subdomains: mapQuestSubDomains});
    var centre = new L.LatLng(53.644638, -2.021484);
             
    this.map.setView(centre, this.defaultZoom).addLayer(mapQuest);
   
    // EXAMPLE: check whether a saved bounds has been parsed to our map object
    if (this.mapOptions.savedbounds != undefined) {
       var sb = this.mapOptions..savedbounds;

       /** the bounds to string function (toBBoxString()) returns lng/lat  for sw/ne, rather than lat/lng... */
       southWest = new L.LatLng(parseFloat(sb[1]), parseFloat(sb[0])),
       northEast = new L.LatLng(parseFloat(sb[3]), parseFloat(sb[2])),
       this.savedBounds = new L.LatLngBounds(southWest, northEast);
       this.map.fitBounds(this.savedBounds);
} 
};

Next on our phtml page we create our map object, restoring the state if it's been set. Bounds for the map would have been saved in our user table in our database. (Leaflet can supply the current bounds as a string - see below) :
mapOptions = new Object();

// Has our user already saved map bounds? Add them to our mapOptions object and parse it to the leaflet maps object
<?php if (!is_null($user->savedBounds)): ?>
    mapOptions['savedbounds'] = <?=$user->savedBounds;?>
<?php endif; ?>

var leaf = new LeafletMap(mapOptions);

Saving the bounds. #mapbounds is a hidden input in a form to hold the bounds string returned by leaflet. We'll give it the maps' current value when the page loads:
var mb = leaf.map.getBounds().toBBoxString();
$('#mapbounds').val(mb)

All that then remains is for us to update this value when we click our form submit button:

$('#submitForm').click(function(){
   var mb = leaf.map.getBounds().toBBoxString();
   $('#mapbounds').val(mb);
});

And that's it!

Comments

Popular Posts