Remove all Markers from map - javascript

I am getting data from Algolia and have a map showing the results using Leaflet when a user searches the results update, the map does too but the markers are not removed and therefore more markers are added to the page.
I assumed that markers.forEach(marker => marker.remove()); would remove my markers but that is not the case.
search.addWidget(
instantsearch.widgets.hits({
container: '#hits',
images: {
},
templates: {
item: document.getElementById('hit-template').innerHTML,
empty: "We didn't find any results for the search <em>\"{{query}}\"</em>"
},
transformItems: function(items) {
renderMap(items);
return items.slice(0, curentResultsPerPage);
},
})
);
const map = L.map(
'mapid', {
renderer: L.canvas(),
zoom: 18,
keepInView: true,
dragging: !L.Browser.mobile,
}
).setMaxZoom(18).setMinZoom(2);
L.mapboxGL({
attribution: '© MapTiler © OpenStreetMap contributors',
accessToken: 'not-needed',
style: 'https://maps.tilehosting.com/c/acad0958-1cbc-46ac-a497-681525e8ca19/styles/streets/style.json?key=iVyYurApGpcJs6fpSZIZ',
}).addTo(map);
let markers = [];
function renderMap(items) {
// remove current markers
markers.forEach(marker => marker.remove());
// clear the markers
markers = [];
// create cluster group
var clusters = L.markerClusterGroup({
chunkedLoading: true,
showCoverageOnHover: false,
});
// iterate through search results
for (var i = 0; i < items.length; i++) {
// get result
var item = items[i];
var geo = item._geoloc;
// create marker
var marker = L.marker([geo.lat, geo.lng], {icon: myIcon});
// create marker popup
marker.bindPopup(item.title);
// add the marker to the markers array
markers.push(marker);
// add the marker to the cluster group
clusters.addLayer(marker);
}
// add the cluster group to the map
map.addLayer(clusters);
if (markers.length) {
map.fitBounds(L.featureGroup(markers).getBounds());
}
}
search.start();

The issue is that the Leaflet Markers in your markers array are actually managed by your clusters Marker Cluster Group. The latter handles the addition and removal of your Markers on its own. Therefore clustered Markers are already removed from your map, and your marker.remove() will do nothing, or temporarily remove the Marker from the map until clusters adds it back.
If markers has the sams list of Markers as in clusters, then simply use the latter instead:
clusters.clearLayers() to get rid of all Markers.
clusters.getBounds() to fit your map to the extent of your Markers.

Related

Add Leaflet Search through a Feature Group

Similar to Search for markers in a markercluster group Leaflet-MarkerCluster
But i am using a Control group ontop of Marker Cluster so they will be displayed upon a radio button click.
var map = L.map("map"),
parentGroup = L.markerClusterGroup(options), // Could be any other Layer Group type.
// arrayOfMarkers refers to layers to be added under the parent group as sub group feature
mySubGroup = L.featureGroup.subGroup(parentGroup, arrayOfMarkers);
parentGroup.addTo( map );
mySubGroup.addTo( map );
I am attempting to implement Leaflet Search - but as per the documentation says it requires a group layer of markers as the second parameter for it work. Trouble is using L.featureGroup.subGroup requires an array of markers.
Attempted to iterate through mySubGroup at run time to get the layers of markers using Leaflet eachLayer but this will duplicate the amount of markers i have on the map for the search to work.
var markersLayer = new L.LayerGroup().addTo( this.map );
forEach( mySubGroup, layers => {
layers.eachLayer( function (layer ) {
console.log ( layer );
markersLayer.addLayer( layer );
})
});
map.addControl( new L.Control.Search({layer: markersLayer}) );
Solved this issue - though it's quite inefficient. If you can find a more elegant solution to avoid duplication then feel free to contribute it as an answer!
var title = layer.options.title;
// iterate through the cluster points
forEach( mySubGroup, layers => {
layers.eachLayer(function (layer) {
var title = layer.options.title; // match the search title to marker title
marker = new L.Circle(new L.LatLng(layer.getLatLng().lat,layer.getLatLng().lng),
{radius: 0, title: title, fill: 'red', fillOpacity: 0, opacity: 0 }); // Create an invisible L circle marker for each cluseter marker
markersLayer.addLayer(marker);
})
});
You then add the markersLayer to the Leaflet Search

How to add google maps marker from array (javascript)?

I hope for a bit support about my following javascript code:
// Initialize Firebase
var config = {
apiKey : "AIzaSyBRC2kza6jhghEFNr5dteVpw2kB9mxqrU8",
authDomain : "formulaire-7fba1.firebaseapp.com",
databaseURL : "https://formulaire-7fba1.firebaseio.com",
projectId : "formulaire-7fba1",
storageBucket : "formulaire-7fba1.appspot.com",
messagingSenderId: "548100244430"
};
firebase.initializeApp(config);
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 0, lng: 0},
zoom: 3,
styles: [{
featureType: 'poi',
stylers: [{ visibility: 'off' }] // Turn off points of interest.
}, {
featureType: 'transit.station',
stylers: [{ visibility: 'off' }] // Turn off bus stations, train stations, etc.
}],
disableDoubleClickZoom: true
});
}
// Loop through users in order with the forEach() method. The callback
// provided to forEach() will be called synchronously with a DataSnapshot
// for each child:
var query = firebase.database().ref("client").orderByKey();
query.once("value").then(function(snapshot) {
var position = [];
snapshot.forEach(function(childSnapshot) {
// key will be "ada" the first time and "alan" the second time
var key = childSnapshot.key;
// childData will be the actual contents of the child
var childData = childSnapshot.val();
position.push(childData.lat + " " + childData.lng);
console.log(position);
});
});
I'm trying to get the array, that's filled with GPS position as a strings, into the google map, as markers. Tried several methods but none works. Can anyone can give me a tip or an direction?
Thanks!
If position is the array that will hold your coordinates. You need to make sure the array elements inside follow a latLng object or what the marker.position property would recognize. Usually it would follow this format:
var latLngObj = {lat: -25.363, lng: 131.044};
You can use your forEach loop to already add a marker per iteration. Before/Aftter pushing the coordinates to the position array do something like:
var marker = new google.maps.Marker({
position: {lat: childData.lat, lng:childData.lng},
map: map
});
I'm not sure how childData actually looks like, as you didn't give that info, but assuming it's a double like -25.363 and not a string, then it will be fine.
You might also want to define your map variable globally so that your functions can recognize it at the part of map: map as you're only defining the map variable inside your initMap function.
Here's the documentation that may guide you on how to add a marker to the map. Just use an iteration (e.g. for loop) to add multiple markers. You'll also see how to delete them in the same documentation.
Also found a relevant stackoverflow post on properly looping to create your markers.
Hope that helps!

Google Maps - get values from location array based on the map's current viewpoint

Edit:
Question = "is there a way to loop through the array and check if each location (long/lat) falls within the current viewport directly" (failing that get all markers within the viewport)
Background:
I have an array of locations (lat, long, id).
I want to:
On a Google Map, use the location array to display markers.
The user can scroll/zoom the map.
Have a button underneath the map, so when the user has decided on an area, he can click the button, and the code will return the ids (from the location array) that are contained within the viewport / map bounds.
There is a .contains for Google, so I guess you could potentially use that with something like
map.getBounds().contains and somehow reference each marker.getPosition()
but I wonder if there's a way to loop through the array and check if each location (long/lat) falls within the current viewport directly
You mean something like this (not tested), map is the google.maps.Map object and needs to be in scope. markersArray is the array of markers.
for (var i=0; i< markersArray.length; i++) {
if (map.getBounds().contains(markersArray[i].getPosition())) {
// the marker is in view
} else {
// the marker is not in view
}
}
http://jsfiddle.net/UA2g2/1/
Thanks geocodezip, you gave me the idea on how to solve it via looping through the array. I don't know if this is the most efficient way, but I put together some code that seems to do what I want - if you check the jsfiddle above and view console you can see that it logs when and which points are in the viewport.
$(document).ready(function(){
var myOptions = {
center: new google.maps.LatLng(51, -2),
zoom: 9,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var storeArray = new Array(["51.38254", "-2.362804", "ID1"], ["51.235249", "-2.297804","ID2"], ["51.086126", "-2.910767","ID3"]);
google.maps.event.addListener(map, 'idle', function() {
for (i = 0; i < storeArray.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(storeArray[i][0], storeArray[i][1]),
map: map
});
}
for (var i=0; i<storeArray.length; i++) {
if (map.getBounds().contains(new google.maps.LatLng(storeArray[i][0], storeArray[i][1]))) {
console.log("marker: " + storeArray[i][2]);
}
}
});
});

Google Maps v3 Marker Always Appears at Top Left

I'm writing some Google Maps API v3 code, which seems to work just fine with multiple markers, but when there's only 1, it always plots the marker in the top left of the map, just beyond the visible area:
Here's my coffeescript code:
class SimpleMap
constructor: (div_id, lat = 40.783627, lng = -73.942583) ->
# L.Icon.Default.imagePath = "/assets"
#div_id = div_id
#map_options = {center: new google.maps.LatLng(lat, lng), zoom: 10, mapTypeId: google.maps.MapTypeId.ROADMAP}
#markers = []
#map = new google.maps.Map document.getElementById(div_id), #map_options
#loadMarkers() # gets them and plots on the map
#autoFit()
loadMarkers: ->
items = $(".grid-item[data-lat], .apartment[data-lat]")
for item in items
console.log "Adding #{item}"
#addMarker(item)
#autoFit()
addMarker: (item) ->
console.log "Adding marker"
lat = $(item).attr("data-lat")
lng = $(item).attr("data-lng")
console.log "#{lat}, #{lng}"
marker = new google.maps.Marker(
position: new google.maps.LatLng lat, lng
map: #map
title: "This is my marker"
)
#markers.push marker
autoFit: ->
bounds = new google.maps.LatLngBounds()
for marker in #markers
bounds.extend marker.getPosition()
#map.fitBounds bounds
# if you leave out the below, the marker appears int he same position as in the screenshot (slightly off screen) but at the max zoom level.
listener = google.maps.event.addListener(#map, "idle", =>
#map.setZoom 9 if #map.getZoom() > 8
#map.setCenter #markers[0].getPosition()
google.maps.event.removeListener listener
)
The map seems to ignore my attempts to set setCenter(#markers[0].getPosition()). Any ideas?
I believe the issue is in:
bounds = new google.maps.LatLngBounds()
for marker in #markers
bounds.extend marker.getPosition()
#map.fitBounds bounds
where you are extending the current map bounds to include all markers, but you have only one marker, the bounds will extend in a way that the marker will be in the map limit border.
Regards
Following the comments this issue occurs only when there is 1 marker.
Based on this fact I would neardown the problem to this line:
#map.fitBounds bounds
When there is only 1 marker, the NE-corner of bounds is equal to the SW-corner.
I noticed unexpected interactions when you use bounds as fitBounds()-argument in this case.
Suggestion:
only use fitBounds() when there are at least 2 markers.

Storing Google Map Markers and Selecting a specific marker from it

I have a webpage that receives AJAX data with values listing_id, lat, lng using $.getJSON. The callback function takes these series of values and creates a Google map marker for each set of listing_id, lat, lng. The marker is then pushed into an array markers and its listing_id into an array markersListingId.
var latLng = new google.maps.LatLng(json[i].lat, json[i].lng);
var marker = new google.maps.Marker({
position: latLng,
icon: base_url + 'images/template/markers/listing.png',
});
markers.push(marker);
markersListingId.push(json[i].listing_id);
Problem: The problem arises when I want to select a specific Marker that corresponds to a particular listing_id, especially in more complicated situations with markers being deleted and added to the markers array.
I can have for loops looping through all the marker's id in markersListingId array then using the loop's index i to get the marker in markers array, but this will make tracking very tricky.
var id_to_select = 1234;
for(var i = 0; i < markersListingId; i++) {
if(markersListingId[i] == id_to_select) {
markers[i].setMap(null);
}
}
Question: How can I store the markers so that I can easily select a specific marker by using its listing_id?
When you create the markers, instead of using an array, can you use a hash table?
http://jsfiddle.net/j9J8x/
var markers = {};
//id goes in place of 1234
n = 1234;
markers[n] = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(0,0)
});
s = '2234'
markers[s] = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(20,0)
});
google.maps.event.addListener(map, 'click', function(event) {
k = 1234;
markers[k].setMap(null);
markers['2234'].setMap(null);
});
}

Categories

Resources