klin
klin

Reputation: 81

Destroy leaflet map trouble

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?

Upvotes: 7

Views: 29082

Answers (4)

Adri
Adri

Reputation: 111

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 function to remove existing map :

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

Hope this help ;)

Upvotes: 3

kathikeyan A
kathikeyan A

Reputation: 1877

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

Upvotes: 13

Shayan
Shayan

Reputation: 966

I had the same problem, and after spending much time on it, the best solution for this problem is to put the map container in a div, and when you want to regenerate the map, remove all of the div's HTML and create a new map container:

<div id="map-bx">
   <div id="map"></div>
</div>
<script type="text/javascript">
    // Map init
</script>

and when you want to regenerate (destroy) the map like so:

<script type="text/javascript">
    $("#map-box").html(""); 
    $("#map-box").html('<div id="map"></div>');
    // map init code
</script>

in my case, map.remove() or map.unload() do not work.

Upvotes: 2

lukaszkups
lukaszkups

Reputation: 5980

maybe try to unload map first? (documentation says that map is being unloaded automatically when using remove method but it's worth to give an additional shot and try unload it manually first)

Upvotes: 0

Related Questions