Leaflet: impossible to remove specific image layer - leaflet

Below are three functions that I use to respectively create a map, add an IMG-layer and remove an IMG-layer. Problem is that when I add an IMG-layer and then want to remove it before adding a new (different) IMG-layer......the removal is not taking place.
The IMG-layers that I use are simple URLs to png's.
So subsequently:
loadMap();
SetLayer("2018_10_13_16_15.png");
RemoveLayer("2018_10_13_16_15.png");
SetLayer("2018_10_13_16_30.png");
Then "2018_10_13_16_15.png" is not removed.
What am I doing wrong??
var map = L.map('map');
var imageBounds = [[50.520, 0.813], [54.295, 10.996]];
function loadMap(){
map.createPane('labels');
var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
attribution: cartodbAttribution
}).addTo(map);
var positronLabels = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png', {
attribution: cartodbAttribution,
pane: 'labels'
}).addTo(map);
map.setView({lat: 52.5, lng: 5.2}, 6.5);
isMap = true; //map is loaded
}
function SetLayer(url) {
IMGLayer = L.imageOverlay(url, imageBounds);
IMGLayer.addTo(map);
}
function RemoveLayer(url) {
IMGLayer = L.imageOverlay(url, imageBounds);
IMGLayer.removeFrom(map);
}

Related

How to automatically set the best view of the map so all markers can be displayed when map loaded?

I have some markers in the map, How to automatically set the best view of the map so all markers can be displayed on the center when map loaded?
I try the following:
var markers = [];
for (let i = 0; i < geoFences.length; i++)
{
var geoFenceLatLon = new L.LatLng(geoFences[i].geoFence_Lat,geoFences[i].geoFence_Lon);
var geoFenceCircle = L.circle(geoFenceLatLon, geoFences[i].geoFence_Radius).addTo(deviceLocation);
markers.push(geoFenceLatLon); //add each markers to array
L.circleMarker([geoFences[i].geoFence_Lat, geoFences[i].geoFence_Lon], { radius: geoFences[i].geoFence_Radius });
L.marker(geoFenceLatLon, {icon: geoFenceMarker}, { pmIgnore: true }).addTo(deviceLocation);
if (i == geoFences.length -1)
{
var group = L.featureGroup(markers); //add markers array to featureGroup
deviceLocation.fitBounds(group.getBounds());
}
}
L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap',
maxZoom: 18
}).addTo(deviceLocation);
but I got:
Uncaught TypeError: t.addEventParent is not a function
at e.addLayer (leaflet.js:5:69635)
at e.initialize (leaflet.js:5:68602)
at new e (leaflet.js:5:2708)
at t.featureGroup (leaflet.js:5:145305)
at renderMap
Thank you so much in advance.
var bounds = new google.maps.LatLngBounds();
....
create marker(s)
//extend bounds by calling this for each marker
bounds.extend(marker.getPosition());
map.fitBounds(bounds);

Leaflet plus Turf.js - dynamically set bounds based on data points

I'm new to Turf.js but have used leaflet before. Looking to move my Google maps over to leafet/turf.js
I'm trying to dynamically set the initial map view by using getBounds as per leaflet, but when using Turf.js, I get an error 'line.getBounds' is not a function.
I've also tried using bbox, to get the bounding box of my datapoints, and whilst I can draw the box on the screen, I can't seem set the initial view to it. I can set the initial view as a static point.
//Some Points
var somePoints = [
[-3.535,55.62],
[-3.54,55.61],
[-3.547,55.6],
[-3.55,55.59],
[-3.57,55.58]
];
var features = turf.points(somePoints);
var center = turf.center(features);
var map = L.map('map').setView([55.6, -3.55], 12);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://openstreetmap.org" target=blank>OpenStreetMap</a> Contributors',
maxZoom: 18,
}).addTo(map);
var line = turf.lineString(somePoints);
var options = {units: 'miles'};
L.geoJSON(line).addTo(map);
var along = turf.along(line, 1.25, options);
L.geoJSON(along).addTo(map).bindTooltip("my tooltip text");
along = turf.along(line, 2.123, options);
L.geoJSON(along).addTo(map).bindTooltip("12345");
var bbox = turf.bbox(line);
var bboxPolygon = turf.bboxPolygon(bbox);
L.geoJSON(bboxPolygon ).addTo(map)
var features = turf.points(somePoints);
var center = turf.center(features);
Updated code - I needed to find the bounds of the turf.js object
//path coords
var coords = [
[-3.535,55.62],
[-3.54,55.61],
[-3.547,55.6],
[-3.55,55.59],
[-3.57,55.58]
];
var features = turf.points(coords );
var center = turf.center(features);
var map = L.map('map');
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://openstreetmap.org" target=blank>OpenStreetMap</a> Contributors',
maxZoom: 18,
}).addTo(map);
var line = turf.lineString(coords);
var options = {units: 'miles'};
L.geoJSON(line).addTo(map);
var along = turf.along(line, 1.25, options);
L.geoJSON(along).addTo(map).bindTooltip("my tooltip text");
along = turf.along(line, 2.123, options);
L.geoJSON(along).addTo(map).bindTooltip("12345");
// get center x/y
var features = turf.points(coords);
var center = turf.center(features);
var centroid_xy = center.geometry.coordinates;
var x = centroid_xy[0];
var y = centroid_xy[1];
// get bounds
var bbox = turf.bbox(line);
var b0 = bbox[0];
var b1 = bbox[1];
var b2 = bbox[2];
var b3 = bbox[3];
L.marker([55.62, -3.535]).bindPopup("Test marker").addTo(map);
var mapMarker2 = L.icon({
iconSize: [16, 16],
iconAnchor: [8, 8],
});
map.setView([y, x], 13);
map.fitBounds([[b1, b0],[b3, b2]]);

Get FeatureId of target in popup on vector layer in Leaflet

The below code works ok, I get lots of interesting data in getFeatureId.
How do I get my hands on that in the popup ?
var map = L.map('map').setView([53.505, -7.09], 7);
L.tileLayer('https://{s}.etc.etc/{z}/{x}/{y}.png', {
attribution: 'osm..'
}).addTo(map);
var VectorTileOptions = {
rendererFactory: L.canvas.tile,
attribution: '',
interactive: true,
getFeatureId:function(feat){
return feat.properties.routes
}
};
var TilesPbfLayer = L.vectorGrid.protobuf(tileurl, VectorTileOptions).addTo(map);
var popup = L.popup();
map.on('popupopen', function(e) {
popup.setContent("how do i get the feature Id ? ")
});
TilesPbfLayer.bindPopup(popup)
I can get a click event on the tile layer, and its got a layer with my stuff in
TilesPbfLayer.on('click', function(e) {
if (e.layer)
popup.setContent(e.layer.properties.routes)
})

Changing overlay layers when switching base layer

I have built a leaflet map with two base layers, and each of these base layers will have their own unique points of interest. The points of interest are being stored as geojson that I loop over to create multiple overlays for different categories. So when viewing the default base layer you would see layers for Show All, Cat1, Cat2 etc.
I need a way to be able to attach overlay layers to a base layer, or remove all overlay layers and then load the relevant ones when the base layer changes.
I tried using the following, which worked to switch categories, with the baselayerchange event, but the overlay layers were still displaying when I switched base layers.
layerControl._layers.forEach(function(layer){
if(layer.overlay){
map.removeLayer(layer.layer)
}
});
I've been searching for a couple of days now for an answer to this without any luck, any help is greatly appreciated.
EDIT
Posting additional code for context. This is not the entirety of the code, there are some plugins that I'm not including code for and have excluded definitions for a several variables, but this should provide better insight into how things are working.
//Initialize the map
var map = new L.Map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: crs1848,
attributionControl: false,
layers: [pano1848]
});
//add controls to the map
var layerControl = L.control.layers(null, null, {position: 'bottomleft'}).addTo(map);
//building category layers from geojson
var types = ['African Americans', 'Art Architecture Culture', 'Education Religion Reform', 'Everyday Life', 'Immigrants', 'Science Inventions', 'Transportation Industry Commerce'];
types.forEach(function(type){
var catType = type.replace(/\s/g,"");
var catPoints = L.geoJson(mapData, {
filter: function(feature, layer){
var cat = feature.properties['category'];
return cat.indexOf(catType) >= 0;
},
onEachFeature: function (feature, layer) {
layer.bindTooltip(feature.properties.name);
(function(layer, properties){
//Create Numeric markers
var numericMarker = L.ExtraMarkers.icon({
icon: 'fa-number',
markerColor: 'yellow',
number: feature.properties['id']
});
layer.setIcon(numericMarker);
layer.on('click', function() {
$.ajax({
url:feature.properties['url'],
dataType:'html',
success: function(result){
$('#detailContainer').html(result);
$('#overlay').fadeIn(300);
}
});
});
})(layer, feature.properties);
}
});
layerControl.addOverlay(catPoints, catType);
});
//Base Layer Change Event
map.on('baselayerchange', function(base){
var layerName;
layerControl._layers.forEach(function(layer){
if(layer.overlay){
map.removeLayer(layer.layer)
}
});
if(base._url.indexOf('1848') >= 0){
map.options.crs = crs1848;
map.fitBounds([
crs1848.unproject(L.point(mapExtent1848[2], mapExtent1848[3])),
crs1848.unproject(L.point(mapExtent1848[0], mapExtent1848[1]))
]);
var southWest = map.unproject([0, 8192], map.getMaxZoom());
var northEast = map.unproject([90112, 0], map.getMaxZoom());
map.setMaxBounds(new L.LatLngBounds(southWest, northEast));
map.addLayer(allPoints);
layerName = '1848 Panorama';
}
else if(base._url.indexOf('2018') >= 0){
map.options.crs = crs2018;
map.fitBounds([
crs2018.unproject(L.point(mapExtent2018[2], mapExtent2018[3])),
crs2018.unproject(L.point(mapExtent2018[0], mapExtent2018[1]))
]);
var southWest = map.unproject([0, 8192], map.getMaxZoom());
var northEast = map.unproject([49152, 0], map.getMaxZoom());
map.setMaxBounds(new L.LatLngBounds(southWest, northEast));
layerName = '2018 Panorama'
}
miniMap.changeLayer(minimapLayers[layerName]);
//map.setView(map.getCenter(), map.getZoom());
});
You may create global variable call "overlays", and remove it like an example below.
Here is the similar example to illustrate your problem jsFiddle
var overlays = {
'Name 1': catPoints,
'Name 2': catType
};
L.control.layers(null, overlays).addTo(map);
// Whenever you want to remove all overlays:
for (var name in overlays) {
map.removeLayer(overlays[name]);
}

How to get all markers on Leaflet

I have a listener that will detect changes of the location of objects on databases. It will pass all the information of the object that is being changed.
I want to get all markers from the current map and find the marker that is affected. Once found, update the location.
But, I am still looking for the best ways to get all markers from the map and then I can update the location.
var map = L.map('map').setView([37.78541,-122.40787], 13);
var markers = new L.FeatureGroup();
var mapLink =
'OpenStreetMap';
L.tileLayer(
'https://{s}.tiles.mapbox.com/v4/examples.map-i87786ca/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoiZ2Vja29iIiwiYSI6IndzVjRGN0kifQ.lToORsjE0lkt-VQ2SXOb-Q', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 18,
}).addTo(map);
var marker = createCircleMarker([44.977368, -93.232659]);
marker._id = "69"; // Id of the marker
map.addLayer(marker);
var socket = io();
socket.on('update location', function(obj) {
// Get all markers and find markers with attribute obj.name to
// update the location to [obj.lat,obj.lon]
});
Use eachLayer method on L.map. Like
map.eachLayer(function (layer) {
if (layer.options.name === 'XXXXX') {
layer.setLatLng([newLat,newLon])
}
});
Documentation at http://leafletjs.com/reference-1.2.0.html#map-eachlayer
To add an option without using map.eachLayer; all layers within the map are internally stored in map._layers.
Use
map._layers.forEach(function (layer) {
...
});
to iterate over ALL Layer elements. Not just the ones currently visible.