Iterate Markers in JavaScript Array vs List - javascript

In this JSFiddle, why is it that I can iterate over neighborhoods[iterate] but not when marker position is set to latLng?
Try both in line 36. When it's set to neighborhood[iterate], the markers drop fine. But when it is set to latLng, they all drop in the same position. I reckon this is related to iteration.
markers.push(new google.maps.Marker({
position: latLng, //[iterator],
I built this example from various examples from Google Maps documentation. How can I fix this? I would prefer to use latLng because it's easier to organize if more information needs to be added. Is that called a JavaScript list? And neighborhoods is a JavaScript array?
Thanks.

There is a scope issue in the call to addMarker().
Here is an example fix in jsFiddle
Fix some code
Referencing the function directly and binding to the index value of the call will help with the issue.
for (var i = 0; i < markersList.length; i++) {
setTimeout(addMarker.bind(this, i), i * 200);
}
Change the function to access the correct index.
function addMarker(i) {
var data = markersList[i]
var latLng = new google.maps.LatLng(data.latLng[0], data.latLng[1]);
markers.push(new google.maps.Marker({
position: latLng,
map: map,
draggable: false,
animation: google.maps.Animation.DROP
}));
}

Related

Optimization for map data

I have large amount of markers I want to display based on user viewpoint. I am looking for most efficient way I can quickly update my map when user changes a viewpoint. In other words display only these markers which falls into bounds (lg, ln).
Currently my solution is following:
On page load pull all data about all places from server and store it in array.
Update map
Every time user drags map remove old markers and place new which falls into bound
Current solutions works but slow and inefficient, to complexity to refresh a map O(N*M) where N old markers which needs to be removed and M new markers which needs to be placed on the map.
I wonder if someone has idea how to make it as faster than this?
How about detecting only the markers which needs to be updated (removed/added)?
I am generally looking for any optimization suggestions - that might be algorithmic improvement, technology or architectural (processing on backend?).
Current code:
var places = function(){} // Some function that pulls a lot of places on page load
function updatePlaces(places){
google.maps.Map.prototype.clearMarkers();
if(places != null){
for(var i = 0; i < places.length; i++){
var lat = places[i].lat;
var lng = places[i].lng;
var position = new google.maps.LatLng(lat, lng);
if(map.getBounds().contains(position) && placedMarkers < markerLimitNumber) {
var marker = new MarkerWithLabel({
position: position,
draggable: false,
raiseOnDrag: true,
map: map,
labelContent: '',
labelAnchor: new google.maps.Point(-10, 15),
labelClass: "labels", // the CSS class for the label
labelStyle: {opacity: 1.0},
icon: 'images/markers/grey_circle_small.png'
});
marker.addListener('click', function(){});
markers.push(marker);
placedMarkers = placedMarkers + 1;
}
}
}
}
google.maps.Map.prototype.clearMarkers = function() {
for(var i=0; i < markers.length; i++){
markers[i].setMap(null);
}
markers = new Array();
placedMarkers = 0;
};
You could try using Google Map Marker Clusterer. It hides the markers at low zoom levels and displays them at higher zoom levels and allows addition of a large number of markers.
Here is a good article on this
https://www.mapbox.com/blog/supercluster/?utm_source=newsletter_april&utm_medium=email&utm_content=supercluster&utm_campaign=newsletter_april
Please take a look

Add a nonstandard marker property

To allow users to delete the correct marker among those on the map, I need to associate each marker with its datastore ID, which is a string. I had originally thought I could set the ID as an integer and use the existing zIndex property of markers. That lead to the code below for creating each physical marker. (But, alas, I was unable to access the integer ID value.)
var marker = new google.maps.Marker({ position: point, map: map , title: text, icon: icon, zIndex: ID});
I don't know how to add a property to the prototype of google.maps.Marker that would hold the ID string, and I imagine it is not advisable to alter such prototypes, anyway. So how is this done? Do I have to use the zIndex property as an index for an array that contains the actual ID's as elements which correspond to the zIndex value? That's awkward, too. Surely there is a better way to do this.
Assuming you have an array of locations:
var markers = [];
for(var i in locations){
var loc = locations[i];
var marker = new google.maps.Marker({
position: loc.point
map: map,
title: loc.text,
icon: loc.icon
});
marker.id = loc.id;
markers.push(marker);
}
You can do this because each marker is just a plain old javascript object.
Then you can define a function to hide markers with particular IDs:
function hideMarkersWithIdIn(ids){
var markersToRemove = markers.filter(function(marker){
return ids.indexOf(marker.id) > -1;
});
markersToRemove.forEach(function(marker){
marker.setMap(null);
});
}
That can be used like
hideMarkersWithIdIn([1,5,3])

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]);
}
}
});
});

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);
});
}

google maps v3 not displaying all markers

I have 19 postal codes in an array which go through GeoCode, it seems to work fine but only 11 of them get displayed. I have searched and tried everything. I have only just started learning JavaScript and the map API, so I'm sure my spelling is wrong on something.
var latlng = new google.maps.LatLng(55.378, -3.435);
myOptions = {
zoom: 5,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("my_canvas"),myOptions);
var geocoder = new google.maps.Geocoder();
var places = ["AB12 3AG","BS11 8AT","IG11 0HN","CA3 0PJ","NR19 1JG","IP11 3HZ","ML4 3LR","WF12 7TH","L33 7YE","M30 9QG","NG18 5DQ","MK12 5QL","PE6 0BN","ME10 3RL","SO40 9HN","B79 7TD","TS2 1RP","GU17 0NP","WV10 7EL"];
for(i = 0; i < places.length; i++){
var address = places[i];
geocoder.geocode({'address':address}, function(results){
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: address
});
});
}
I think that all the post codes do load because the title for all the markers is the last address in the array 'WV10', but like I said, only 11 out of the 19 locations get displayed.
The problem is that you are creating a function in a loop. At least this is the problem for the label. A solution for this is to create a new scope be calling a function inside the loop:
for(i = 0; i < places.length; i++){
(function(place) {
geocoder.geocode({'address':place}, function(results){
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: place
});
});
}(places[i]));
}
This might also solve the display problem, but I'm not sure about this. Could it be that some places resolve to the same or very close positions?

Categories

Resources