I have a Leaflet map with custom markers.
Recently I added Layer Control so that I can make use of a legend to filter the markers.
I've managed to add the legend however it appears to recreate all the markers on top of my custom ones and filters those instead.
I know I'm doing something wrong in the code but can't figure out where.
How can I filter my custom markers using the legend/layer control ?
Here is my jsfiddle
var markersA = [];
var markersB = [];
var markersC = [];
//Loop through the initial array and add to two different arrays based on the specified variable
for (var i = 0; i < data.length; i++) {
switch (data[i].Category) {
case 1:
markersA.push(L.marker([data[i].lat, data[i].lng]));
break;
case 2:
markersB.push(L.marker([data[i].lat, data[i].lng]));
break;
case 3:
markersC.push(L.marker([data[i].lat, data[i].lng]));
break;
default:
break;
}
}
//add the groups of markers to layerGroups
var groupA = L.layerGroup(markersA);
var groupB = L.layerGroup(markersB);
var groupC = L.layerGroup(markersC);
const myAPIKey = "**";
var tileLayer = {
'Filter drop off Points:': L.tileLayer('http://{s}.tile.cloudmade.com/{key}/22677/256/{z}/{x}/{y}.png')
};
const layer = 'https://api.maptiler.com/maps/uk-openzoomstack-night/{z}/{x}/{y}.png?key=tbRG4BpdjpPfpJ5rjwZY'
const layer2 = 'https://api.maptiler.com/maps/voyager/{z}/{x}/{y}.png?key=tbRG4BpdjpPfpJ5rjwZY'
var osm = L.tileLayer(layer)
const map = L.map('map', {
center: data[data.length - 12],
zoomControl: true,
zoom: 17,
layers: [osm, groupA, groupB, groupC]
});
// 'translate(0,' + (-outerRadius + 7) + ')')
var overlayMaps = {
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=green&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Delivered": groupA,
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=gold&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Left": groupB,
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=red&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Returned": groupC
};
L.control.layers(tileLayer, overlayMaps, {
collapsed: false,
position: 'topright'
}).addTo(map);
var mygeojson = {
type: "FeatureCollection",
features: [],
};
var waypoints = []
var all_points = []
for (i = 0; i < data.length; i++) {
var lng = data[i].lng;
var lat = data[i].lat;
all_points.push([lng, lat]);
if (data[i].Category != 0) {
mygeojson.features.push({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [data[i].lng, data[i].lat]
},
"properties": {
"Icon": data[i].Icon,
"Status": data[i].Status,
"Customer": data[i].Customer,
"Supplier": data[i].Supplier,
"Item Size": data[i]["Item Size"],
"Address": data[i].Address,
"Customer Order": data[i]["Customer Order"],
"Notes": data[i].Notes,
"Instruction": data[i].Instruction
}
});
waypoints.push({
id: data[i].id,
lat: data[i].lat,
lng: data[i].lng
});
}
}
// console.log(mygeojson);
//console.log(all_points);
var polyline = L.polyline(lngLatArrayToLatLng(all_points)).addTo(map);
function lngLatArrayToLatLng(lngLatArray) {
return lngLatArray.map(lngLatToLatLng);
}
function lngLatToLatLng(lngLat) {
return [lngLat[1], lngLat[0]];
}
function IconStyle(feature, latlng) {
switch (feature.properties["Status"]) {
case "Delivered":
var deliveredIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=green&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: deliveredIcon
});
case "Left":
var leftIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=gold&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: leftIcon
});
case "Returned":
var returnedIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=red&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: returnedIcon
});
}
}
Best Answer
Since you are adding your markers to
groupA
,groupB
andgroupC
layers and also to GeoJSON layer that uses the same data frommygeojson
GeoJSON object and all these layers are added to the map, it's normal you will get your markers twice.Solution to select desired markers from GeoJSON layer with layer control would be to break your GeoJSON layer to three different layers, using
filter
option to select only layers of desired category for each of those layers.Fro this you would have to add
Category
property when creating your GeoJSON obkect:Than you can wrap you GeoJSON layer creation into a function, where one of the parameters is
category
to filter data only for desired category:Then you can create three different GeoJSON layers, corresponding to the three categories, and use those in layer control:
See working JSFiddle: https://jsfiddle.net/TomazicM/ct9pj8n1/