Reputation: 13
Something changed between Leaflet 1.0.3 and 1.1.0 that makes it where I can no longer dynamically remove all layers on a map and then add a new set of layers in their place.
To add a set of waypoints and the base map (single image):
function drawMap() {
waypointLayer = L.layerGroup([]);
var bounds = [[0, 0], [30, 30]];
L.imageOverlay(
"https://www.dropbox.com/s/r098ggmze3763fx/examplemap.png?raw=1",
bounds
).addTo(ourMap);
ourMap.fitBounds(bounds);
for (var wp of waypoints[showPoints]) {
waypointLayer.addLayer(
L.rectangle([[wp[0] + 0.2, wp[1] - 0.2], [wp[0] - 0.2, wp[1] + 0.2]], {
color: "black",
fillColor: "black",
fillOpacity: 0.9
})
);
}
ourMap.addLayer(waypointLayer);
}
To erase all layers, I'm using:
ourMap.eachLayer(function(thisLayer) {
ourMap.removeLayer(thisLayer);
});
I've set up a codepen with Leaflet 1.2.0 at https://codepen.io/cablemonkey42/pen/wpayaX.
For a working 1.0.3 example using the same exact code: https://codepen.io/cablemonkey42/pen/PEqRyq
Other than my probably obvious novice skills, can anyone please point me to what I'm doing wrong? Thanks
Upvotes: 1
Views: 1019
Reputation: 53185
Looks like there is indeed a regression between Leaflet version 1.1.0+ and 1.0.3-, triggered by the fact that you remove the SVG renderer layer (that is automatically added by Leaflet) onto which your Rectangles are drawn.
You have several "easy" workarounds for the time being:
$("#mapset").change(function() {
//Erase everything shown
/*ourMap.eachLayer(function(thisLayer) {
ourMap.removeLayer(thisLayer);
});*/
/////////////////////////////////////////////////////////////
// Erase only the explicitly added layers,
// in order to preserve automatically managed layers (Renderer).
if (imageOverlay) {
imageOverlay.remove();
}
if (waypointLayer) {
waypointLayer.remove();
}
/////////////////////////////////////////////////////////////
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
var ourMap; //LeafletJS Map
var waypointLayer; //LayerGroup of Waypoints
/////////////////////////////////////////////////////////////
var imageOverlay; // Reference to explicitly added layer.
/////////////////////////////////////////////////////////////
//The variable "waypoints" is two different sets of waypoints.
//Which waypoint shown is defined by "showPoints".
var waypoints = [];
waypoints[0] = [
[5, 5],
[10, 5],
[20, 20]
];
waypoints[1] = [
[25, 25],
[20, 15],
[10, 10]
];
var showPoints = 0;
$(function() {
//Initialize map and draw default data
ourMap = L.map("ourmap", {
crs: L.CRS.Simple,
minZoom: 3,
maxZoom: 10,
zoomDelta: 1,
zoomSnap: 0.01
});
drawMap();
});
$("#mapset").change(function() {
//Erase everything shown
/*ourMap.eachLayer(function(thisLayer) {
ourMap.removeLayer(thisLayer);
});*/
/////////////////////////////////////////////////////////////
// Erase only the explicitly added layers,
// in order to preserve automatically managed layers (Renderer).
if (imageOverlay) {
imageOverlay.remove();
}
if (waypointLayer) {
waypointLayer.remove();
}
/////////////////////////////////////////////////////////////
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
function drawMap() {
waypointLayer = L.layerGroup([]);
var bounds = [
[0, 0],
[30, 30]
];
//assign a base map (blank tan-ish map for demo, normally I would change based on data set)
/////////////////////////////////////////////////////////////
// Keep a reference to each explicitly added layer.
imageOverlay = L.imageOverlay(
"https://www.dropbox.com/s/r098ggmze3763fx/examplemap.png?raw=1",
bounds
).addTo(ourMap);
/////////////////////////////////////////////////////////////
//zoom to show the entire base map image
ourMap.fitBounds(bounds);
//add each waymark of our selected set to a layergroup
for (var wp of waypoints[showPoints]) {
waypointLayer.addLayer(
L.rectangle([
[wp[0] + 0.2, wp[1] - 0.2],
[wp[0] - 0.2, wp[1] + 0.2]
], {
color: "black",
fillColor: "black",
fillOpacity: 0.9
})
);
}
//add the layergroup to the map
ourMap.addLayer(waypointLayer);
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Waypoint Set:
<select id="mapset">
<option value="0" selected>0</option>
<option value="1">1</option>
</select>
<div id="ourmap" style="height: 170px"></div>
L.Renderer
.$("#mapset").change(function() {
//Erase everything shown
ourMap.eachLayer(function(thisLayer) {
/////////////////////////////////////////////////////////////
// Skip Renderer type layers.
if (thisLayer instanceof L.Renderer) {
return;
}
/////////////////////////////////////////////////////////////
ourMap.removeLayer(thisLayer);
});
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
var ourMap; //LeafletJS Map
var waypointLayer; //LayerGroup of Waypoints
//The variable "waypoints" is two different sets of waypoints.
//Which waypoint shown is defined by "showPoints".
var waypoints = [];
waypoints[0] = [
[5, 5],
[10, 5],
[20, 20]
];
waypoints[1] = [
[25, 25],
[20, 15],
[10, 10]
];
var showPoints = 0;
$(function() {
//Initialize map and draw default data
ourMap = L.map("ourmap", {
crs: L.CRS.Simple,
minZoom: 3,
maxZoom: 10,
zoomDelta: 1,
zoomSnap: 0.01
});
drawMap();
});
$("#mapset").change(function() {
//Erase everything shown
ourMap.eachLayer(function(thisLayer) {
/////////////////////////////////////////////////////////////
// Skip Renderer type layers.
if (thisLayer instanceof L.Renderer) {
return;
}
/////////////////////////////////////////////////////////////
ourMap.removeLayer(thisLayer);
});
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
function drawMap() {
waypointLayer = L.layerGroup([]);
var bounds = [
[0, 0],
[30, 30]
];
//assign a base map (blank tan-ish map for demo, normally I would change based on data set)
L.imageOverlay(
"https://www.dropbox.com/s/r098ggmze3763fx/examplemap.png?raw=1",
bounds
).addTo(ourMap);
//zoom to show the entire base map image
ourMap.fitBounds(bounds);
//add each waymark of our selected set to a layergroup
for (var wp of waypoints[showPoints]) {
waypointLayer.addLayer(
L.rectangle([
[wp[0] + 0.2, wp[1] - 0.2],
[wp[0] - 0.2, wp[1] + 0.2]
], {
color: "black",
fillColor: "black",
fillOpacity: 0.9
})
);
}
//add the layergroup to the map
ourMap.addLayer(waypointLayer);
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Waypoint Set:
<select id="mapset">
<option value="0" selected>0</option>
<option value="1">1</option>
</select>
<div id="ourmap" style="height: 170px"></div>
preferCanvas
map option). The former seems immune to this bug.$(function() {
//Initialize map and draw default data
ourMap = L.map("ourmap", {
crs: L.CRS.Simple,
minZoom: 3,
maxZoom: 10,
zoomDelta: 1,
zoomSnap: 0.01,
/////////////////////////////////////////////////////////////
preferCanvas: true // Use Canvas that is immune to SVG Renderer bug.
/////////////////////////////////////////////////////////////
});
drawMap();
});
var ourMap; //LeafletJS Map
var waypointLayer; //LayerGroup of Waypoints
//The variable "waypoints" is two different sets of waypoints.
//Which waypoint shown is defined by "showPoints".
var waypoints = [];
waypoints[0] = [
[5, 5],
[10, 5],
[20, 20]
];
waypoints[1] = [
[25, 25],
[20, 15],
[10, 10]
];
var showPoints = 0;
$(function() {
//Initialize map and draw default data
ourMap = L.map("ourmap", {
crs: L.CRS.Simple,
minZoom: 3,
maxZoom: 10,
zoomDelta: 1,
zoomSnap: 0.01,
/////////////////////////////////////////////////////////////
preferCanvas: true // Use Canvas that is immune to SVG Renderer bug.
/////////////////////////////////////////////////////////////
});
drawMap();
});
$("#mapset").change(function() {
//Erase everything shown
ourMap.eachLayer(function(thisLayer) {
ourMap.removeLayer(thisLayer);
});
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
function drawMap() {
waypointLayer = L.layerGroup([]);
var bounds = [
[0, 0],
[30, 30]
];
//assign a base map (blank tan-ish map for demo, normally I would change based on data set)
L.imageOverlay(
"https://www.dropbox.com/s/r098ggmze3763fx/examplemap.png?raw=1",
bounds
).addTo(ourMap);
//zoom to show the entire base map image
ourMap.fitBounds(bounds);
//add each waymark of our selected set to a layergroup
for (var wp of waypoints[showPoints]) {
waypointLayer.addLayer(
L.rectangle([
[wp[0] + 0.2, wp[1] - 0.2],
[wp[0] - 0.2, wp[1] + 0.2]
], {
color: "black",
fillColor: "black",
fillOpacity: 0.9
})
);
}
//add the layergroup to the map
ourMap.addLayer(waypointLayer);
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Waypoint Set:
<select id="mapset">
<option value="0" selected>0</option>
<option value="1">1</option>
</select>
<div id="ourmap" style="height: 170px"></div>
You can also easily patch the SVG Renderer code:
L.SVG.include({
_destroyContainer: function() {
L.DomUtil.remove(this._container);
L.DomEvent.off(this._container);
delete this._container;
delete this._rootGroup;
// Make sure to also clear the cache for svgSize,
// so that next container width and height will be set.
delete this._svgSize;
}
});
/////////////////////////////////////////////////////////////
// Patch SVG Renderer code to remove regression bug.
L.SVG.include({
_destroyContainer: function() {
L.DomUtil.remove(this._container);
L.DomEvent.off(this._container);
delete this._container;
delete this._rootGroup;
// Make sure to also clear the cache for svgSize,
// so that next container width and height will be set.
delete this._svgSize;
}
});
/////////////////////////////////////////////////////////////
var ourMap; //LeafletJS Map
var waypointLayer; //LayerGroup of Waypoints
//The variable "waypoints" is two different sets of waypoints.
//Which waypoint shown is defined by "showPoints".
var waypoints = [];
waypoints[0] = [
[5, 5],
[10, 5],
[20, 20]
];
waypoints[1] = [
[25, 25],
[20, 15],
[10, 10]
];
var showPoints = 0;
$(function() {
//Initialize map and draw default data
ourMap = L.map("ourmap", {
crs: L.CRS.Simple,
minZoom: 3,
maxZoom: 10,
zoomDelta: 1,
zoomSnap: 0.01
});
drawMap();
});
$("#mapset").change(function() {
//Erase everything shown
ourMap.eachLayer(function(thisLayer) {
ourMap.removeLayer(thisLayer);
});
//assign showPoints to whichever waypoint set (0 or 1) we want to show
showPoints = $(this).val();
//now draw it...
drawMap();
});
function drawMap() {
waypointLayer = L.layerGroup([]);
var bounds = [
[0, 0],
[30, 30]
];
//assign a base map (blank tan-ish map for demo, normally I would change based on data set)
L.imageOverlay(
"https://www.dropbox.com/s/r098ggmze3763fx/examplemap.png?raw=1",
bounds
).addTo(ourMap);
//zoom to show the entire base map image
ourMap.fitBounds(bounds);
//add each waymark of our selected set to a layergroup
for (var wp of waypoints[showPoints]) {
waypointLayer.addLayer(
L.rectangle([
[wp[0] + 0.2, wp[1] - 0.2],
[wp[0] - 0.2, wp[1] + 0.2]
], {
color: "black",
fillColor: "black",
fillOpacity: 0.9
})
);
}
//add the layergroup to the map
ourMap.addLayer(waypointLayer);
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Waypoint Set:
<select id="mapset">
<option value="0" selected>0</option>
<option value="1">1</option>
</select>
<div id="ourmap" style="height: 170px"></div>
Upvotes: 1