I am trying to build a web map with a number of layers that can be toggled on and off. Initially the map gets drawn without any issues, but when I try to toggle off any layer, a new map is added below the existing one (instead of replacing it).
When I toggle off a layer, a javascript refresh() function is called. This function needs to rebuild the list of layers to draw and then call again the function that builds the map. I was hoping this would just replace the existing, but instead a new map gets added below.
...
...
<script type="text/javascript" src="ol.js"></script>
<script defer="defer" type="text/javascript">
function onLOAD()
{
var my_layers = 'layer_1, \
layer_2, \
layer_3, \
...'
init(my_layers);
}
function init(my_layers){
//The bounding box of Lund:lund_address_point
var extent = [13.1267,55.6770,13.2601,55.7597];
//Initial view
var view = new ol.View({
center: ol.proj.transform([13.192927, 55.708944], 'EPSG:4326', 'EPSG:3857'),
zoom: 13
});
//The source for the layers
var wmsSource = new ol.source.ImageWMS({
url: 'http://localhost:8080/geoserver/Test/wms',
params: {
'LAYERS': my_layers
},
serverType: 'geoserver'
});
//OpenStreetMap background and my_layers
var layers = [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Image({
source: wmsSource
})
];
//Bind the map object to our "map" div and add some extra functionality
var map = new ol.Map({
layers: layers,
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}).extend([
//Extra functionality of the map
//Control for displaying coordinates
new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(4),
projection: 'EPSG:4326',
className: 'custom-mouse-position',
target: document.getElementById('location'),
undefinedHTML: ' '
}),
//Control for displaying a scale line
new ol.control.ScaleLine({
target: document.getElementById('scale-line')
}),
//Control for zooming to a defined extent
new ol.control.ZoomToExtent({
extent: ol.proj.transform(extent, 'EPSG:4326', 'EPSG:3857')
})
]),
target: 'map',
view: view
});
}
function refresh(){
my_layers='';
if (layer_1.checked) my_layers = my_layers + "layer_1,";
if (layer_2.checked) my_layers = my_layers + "layer_2,";
if (layer_3.checked) my_layers = my_layers + "layer_3,";
...
if (my_layers.length > 1){
my_layers = my_layers.substring(0,my_layers.length-1);
}
init(my_layers);
}
</script>
</head>
<body onload="onLOAD()">
<div>
<br><input type="checkbox" id="layer_1" value="layer_1" checked="checked" onClick="refresh()">Layer_1
<br><input type="checkbox" id="layer_2" value="layer_2" checked="checked" onClick="refresh()">Layer_2
<br><input type="checkbox" id="layer_3" value="layer_3" checked="checked" onClick="refresh()">Layer_3
...
...
</div>
<br>
<div id="map"></div>
<br>
<div id="wrapper">
<div id="location"></div>
<br>
<div id="scale-line" class="scale-line"></div>
</div>
...
...
To cleanly remove the old map you need to call map.setTarget(null)
on the previous Map object.
But in your case it might be better to only create a single map and update the layers' visibility. This way the map / view states like loaded tiles, center and zoom are remembered.
<div>
<br><input type="checkbox" id="input-osm" value="osm" checked="checked">OSM
<br><input type="checkbox" id="input-image" value="image" checked="checked">Image
</div>
Declare the map and layers variables outside the init function so it can be accessed from the refresh function.
var map, layers;
Store your layers in an object and assign to declared layers variable to be able to reference them by name and initialize them with correct visibility:
layers = {
osm: ol.layer.Tile({
source: new ol.source.OSM(),
visible: document.getElementById('input-osm').checked,
}),
image: new ol.layer.Image({
source: wmsSource
visible: document.getElementById('input-image').checked,
})
};
Assign map with all layers to previously declared variable:
map = new ol.Map({
layers: Object.values(layers),
...
On user input layers' visibility should be changed according to the checkbox:
function refresh(checkbox) {
layers[checkbox.value].setVisible(checkbox.checked);
}
document.getElementById('input-osm').addEventListener('change', refresh);
document.getElementById('input-image').addEventListener('change', refresh);
Best of luck.