Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destroy leaflet map trouble

Tags:

leaflet

I use several leaflet maps at one time. They can be created and deleted dynamically. But when a map is destroyed by using the map.remove() there is a memory leak. Detached DOM trees appears. You can see it in Chrome Dev Tools.

Screenshot with a leak.

Example function I use to recreate div and map:

var map, mapDiv;
recreateMap = function(){
    // destroy previous map and div
    if(map) map.remove();
    if(mapDiv) mapDiv.parentNode.removeChild(mapDiv);
    // create new map div
    var randomDivId = 'mapId' + new Date().getTime();
    mapDiv = document.createElement('div');
    mapDiv.id = randomDivId;
    mapDiv.style.height = '200px';
    mapDiv.style.width = '200px';
    document.getElementsByTagName('body')[0].appendChild(mapDiv);
    // attach map to div
    map = L.map(randomDivId).setView([51.505, -0.09], 13);  
    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map);
    map.invalidateSize();
};

Working example here.

How to properly destroy the leaflet maps?

like image 379
klin Avatar asked May 20 '14 07:05

klin


2 Answers

Assume you create a leaflet map with some thing like the following

var lat =39, long = 40;
var coords=[lat,long];
var zoomLevel=13;

var mapInstance = leafLet.map(mapContainerId).setView(coords, zoomLevel);

You can remove it using the following code

if (mapInstance && mapInstance.remove) {
  mapInstance.off();
  mapInstance.remove();
}

If you are working with non blocking javascript code or async calls, if required you can use a timer to ensure that your code does not error out. Following is a sample implementation of the same

var timeoutIndex=0;
var watcher=window.setInterval(function(){
  timeoutIndex++;
  if (mapInstance && mapInstance.remove) {
      mapInstance.off();
      mapInstance.remove();
      window.clearInterval(watcher);
  }
  if(timeoutIndex >50) {  //wait for 5 seconds before giving up
      window.clearInterval(watcher);
  }  
},100);

It worked for me. Guess it helps you too

like image 103
kathikeyan A Avatar answered Nov 09 '22 06:11

kathikeyan A


If you have several maps, you need to put each map into diffents var.

var map1 = L.map(mapDiv1);
var map2 = L.map(mapDiv2);

You can also create a function to control map initialisation and container :

function BoolMapInit(map, mapDiv) {
    return (map != null && map._container.id == divMap);
}

And the fonction to remove existing map :

function RemoveExistingMap(map) {
    if (map != null) {
        map.remove();
        map = null;
    }
}

Hope this help ;)

like image 28
Adri Avatar answered Nov 09 '22 05:11

Adri