I have this piece of javascript code
var myOptions = {
zoom:9,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var latlongcollection = new Array();
// some more code to push latlng objects into latlongcollection
map.setCenter(latlongcollection[0]);
for(latlong in latlongcollection){
map.getBounds().extend(latlong);
}
map.fitBounds(map.getBounds());
But everytime its giving me error map.getBounds() is undefined. center is set and even. zoom is set before I call map.getBounds(). Please help
Try using a new google.maps.LatLngBounds object instead of map.getBounds():
var bounds = new google.maps.LatLngBounds()
// note: this for/in loop is erronous
//for(latlong in latlongcollection){
// bounds.extend(latlong);
//}
for ( var i = 0,len=latlongcollection.length;i<len;i++) {
bounds.extend( latlongcollection[ i ] );
}
map.fitBounds( bounds );
Also, the for loop you use is bad in conjunction with arrays. A for/in on an array will loop not only over indexed values, but also properties and methods. So you will be extending you bounds with .length and .push and so on. This alone might've also caused the bug. Always read for/in loops as:
for property in object
Which includes methods and so on.
Related
I have been working on rendering a google map, using the code below: I have put it through a syntax tree ECMAScript parser and it looks to be syntactically correct about >95%.
var mapfeats = function createMap(){
options = {
zoom: 4,
center: new google.maps.LatLng( 36.73, 10 ),
mapTypeId: google.maps.MapTypeId.ROADMAP,
},
map = new google.maps.Map(
document.onmouseover.getElementById( 'map-canvas' ),
options);
var bub1 = map.Data.Point(function(map){ var vro = lat(35.0761882) + "" + lng(1.04515982)});
var bub2 = map.Data.Point(function(map){ var whr = lat(40.5569782) + "" + lng(8.56081142)});
var pup = bub1[LatLng({split("vro")[9]})] + bub2[LatLng({split("whr")[9]})]
for (pup.length[i]; i += say, say = 37; say--) {
forEach(map.Marker(function(pup){ map.getShape("oval") }) );
}};
function mapit(){
var pt = mapfeats("pup");
for( index = 0; void pt < pup.length || index++; index < pt.length) {
var coor = pup.split(9);
latlng = new google.maps.LatLng( coor[0], coor[1], coor[2], coor [3] );
marker = new google.maps.Marker( {position: latlng, map: map},{clickable: true, mapfeats, map:map});
marker.setMap( map );
}};
Now what I don't seem to understand is when I debug using the Chrome console. I have used the maps api as the source from which to debug. As I have inputted functions into the console the I encountered:
google.maps.Map({lat: 35.0761882, lng: 1.04515982})
`main.js:53 Uncaught TypeError: this[Lb] is not a function `
`at Object.Vk [as Map] (http://maps.gstatic.com/maps-api-v3/api/js/20/11b/main.js:53:915)`
Taking a look at the library, they define the aruguement wasn't evaluated bc it wasn't a function:
`var c=b||{};te(c.mapTypeId)||(c.mapTypeId="roadmap");this[Lb](c)`
therefore I was hoping to ask
(a) Are functions supposed to be defined w/in Map object literals to the extent that a compiler would check it. I am working from : JS Fiddle and have the frame that renders without map. I currently do not have the spidermonkey compiler. And would like to know why this is not compilable if it works with the ECMASCRIPT syntax tree thus the tokens should be translated into bytecode.
(b) Objective use-cases for other Map API instances that have used compiling methods in the browser. I am still quote new to the functionality of the browser dev environment.
Thanks you for yourr help .
This {lat: 35.0761882, lng: 1.04515982} is not a valid MapOptions object, it is a LatLngLiteral
google.maps.Map({lat: 35.0761882, lng: 1.04515982})
It needs to be:
google.maps.Map(document.getElementById('map-canvas'),{center:{lat: 35.0761882, lng: 1.04515982},zoom:3})
(center and zoom are required and the google.maps.Map constructor takes a DOM node as its first argument)
I'm working a django project using the google maps JS api.
Basically what's going on here is that I'm creating a map centered at a point (works perfectly), drawing a bunch of points specified by the journey variable (value is substituted in by django template),
and then trying to draw a polyine between these points. (Fails to produce a polyline with a "Uncaught TypeError: number is not a function" at the JS console.)
The traceback at the JS console is pretty indecipherable to me, particularly due to all the .js files being minned.
When I log the path attribute of the polyline, and the coordinate I'm adding (as seen below), everything seems to work. I know the coord is formatted correctly, because I think Marker and Polyline should take the same datatype (LatLng) for their locations, and the Markers work fine. Anyone have any idea what's happening?
var mapOptions = {
center: { lat: 37.23112,
lng: -122.29398
},
zoom: 15
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Make the line that will trace the guys route:
var polyOptions = {
strokeColor: '#000000',
srokeOpacity: 1.0,
strokeWeight: 3
};
var poly = new google.maps.Polyline(polyOptions);
poly.setMap(map);
// Make an array of everywhere the lilguys has been. Passed into this django template as {"lat": 12, "lng": 8} objects.
var journey = [{"lat": 33.2389, "lng":-123.9349}, {"lat":32.928392, "lng":-122.29289}, {"lat":33.928982, "lng":-120.298392}];
var journey_markers = [];
// Draw all the placemarks
for (var i = 0; i < journey.length; i++) {
var coord = journey[i];
journey_markers.push(new google.maps.Marker({position: coord, map:map}));
var path = poly.getPath();
console.log(coord);
console.log(path);
path.push(coord);
}
Thank you!
EDIT:
I substituted the template variables in for what they evaluate to. This was checked by looking at the HTML source code in the browser, and confirmed to not be the source of the bug.
Figured out the answer. It seems to be that unlike Markers, the Polyine path requires google.maps.LatLng() objects rather than latlng literals.
The following fixes the issue:
...
// Draw all the placemarks
for (var i = 0; i < journey.length; i++) {
var coord = new google.maps.LatLng(journey[i].lat, journey[i].lng);
...
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]);
}
}
});
});
The approach I took thus far has been:
function addMarker( query ) {
var geocoder = new google.maps.Geocoder();
var afterGeocode = $.Deferred();
// Geocode 'query' which is the address of a location.
geocoder.geocode(
{ address: query },
function( results, status ){
if( status === 'OK' ){
afterGeocode.resolve( results ); // Activate deferred.
}
}
);
afterGeocode.then( function( results ){
var mOptions = {
position: results[0].geometry.location,
map: map
}
// Create and drop in marker.
var marker = new google.maps.Marker( mOptions );
marker.setAnimation( google.maps.Animation.DROP );
var current_bounds = map.getBounds(); // Get current bounds of map
// use the extend() function of the latlngbounds object
// to incorporate the location of the marker
var new_bounds = current_bounds.extend( results[0].geometry.location );
map.fitBounds( new_bounds ); // fit the map to those bounds
});
}
The problem I'm running into is that the map inexplicably zooms out by some amount, no matter if the new marker fits within the current viewport or not.
What am I doing wrong?
ADDENDUM
I added logs and an additional variable to capture the map bounds after the transition was made (new_new_bounds)
current_bounds = // Map bounds before anything is done.
{-112.39575760000002, 33.60691883366427},
{-112.39295444655761, 33.639099}
new_bounds = // From after the extend
{-112.39295444655761, 33.60691883366427},
{-112.39575760000002, 33.639099}
new_new_bounds = // From after the fitbounds
{-112.33942438265382, 33.588697452015374},
{-112.44928766390382, 33.657309727063996}
OK, so after much wrangling, it turns out that the problem was a map's bounds are not the same as a map's bounds after fitBounds(). What happens (I presume), is Google takes the bounds you give it in the fitBounds() method, and then pads them. Every time you send the current bounds to fitBounds(), You're not going to fit bounds(x,y), you're going to fit bounds(x+m,y+m) where m = the arbitrary margin.
That said, the best approach was this:
var current_bounds = map.getBounds();
var marker_pos = marker.getPosition();
if( !current_bounds.contains( marker_pos ) ){
var new_bounds = current_bounds.extend( marker_pos );
map.fitBounds( new_bounds );
}
So, the map will only fit bounds if a marker placed falls outside the current map bounds. Hope this helps anyone else who hits this problem.
A possible explanation is that you randomly placed your new marker into the gap of the z-curve. A z-curve recursivley subdivide the map into 4 smaller tiles but that's also the reason why there are gaps between the tiles. A better way would be to use a hilbert curve or a moore curve for map applications. There is a patented search algorithm covering this issue, I think it is called multidimensional range query in quadtrees. You want to look for Nick's hilbert curce quadtree spatial index blog.
I have the following code in which I would expect the contains method to return true, but it returns false:
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(55.38942944437183, -2.7379201682812226),
new google.maps.LatLng(54.69726685890506, -1.2456105979687226)
);
var center = bounds.getCenter(); // (55.04334815163844, -1.9917653831249726)
var x = bounds.contains(center); // returns false
On the same page, where map is a reference to the Map object, the following code returns true as expected:
map.getBounds().contains(map.getBounds().getCenter())
Why might my call to bounds.contains be returning false?
Ah, brilliant. The google.maps.LatLngBounds constructor expects SouthWest and NorthEast LatLng parameters. I have somehow bungled up my coordinates and passed in NorthWest and SouthEast instead!
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(54.69726685890506,-2.7379201682812226),
new google.maps.LatLng(55.38942944437183, -1.2456105979687226)
);
var center = bounds.getCenter(); // still returns (55.04334815163844, -1.9917653831249726)
var x = bounds.contains(center); // now returns true
Lesson learned: getCenter doesn't care if you created the LatLngBounds with NorthWest and SouthEast instead, but if you want contains to return a useful answer you better pass in the suggested SouthWest and NorthEast!
I guess its easier to try this. It works for me without having to worry about NE orSW
var bounds = new google.maps.LatLngBounds();
bounds.extend(54.69726685890506,-2.7379201682812226);
bounds.extend(55.38942944437183, -1.2456105979687226);
var center = bounds.getCenter(); // still returns (55.04334815163844, -1.9917653831249726)
var x = bounds.contains(center); // now returns true
I know this post is old, but I came searching for answers here, so thought of updating from what I have learnt.
This is the way that it worked for me:
var bounds = new google.maps.LatLngBounds();
bounds.extend(54.69726685890506,-2.7379201682812226);
bounds.extend(55.38942944437183, -1.2456105979687226);
map.fitBounds(bounds);