I'm using Google Maps and Google Geocoding service for my location service application. I use Google Geocoding service for translating address to lat/lng position. My problem is how to automatically find an appropriate zoom for a certain address like the maps.google.com does.
For example, when I search a street in maps.google.com (e.g. Cisitu Baru, Bandung), it will show the street in smaller zoom. When I search a region (e.g. Bandung), it will show larger zoom. And a larger zoom for province (e.g. Jawa Barat / West Java), and so on.
I have tried both
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {
'address': someAddress
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.dir(results);
//cut
map.panToBounds(results[0].geometry.bounds); //setting bound
//cut
}
});
and
//cut
map.panToBounds(results[0].geometry.viewports); //setting bound
//cut
(Honestly, I still don't know what's the difference between bounds and viewport and what are their uses from code.google.com/apis/maps/documentation/javascript/geocoding.html)
but both still don't display the map in appropriate zoom.
Right now, I use a small hack like this
var tabZoom = {
street_address: 15,
route: 15,
sublocality: 14,
locality: 13,
country: 10
};
//cut
map.setCenter(results[0].geometry.location);
if (tabZoom[results[0].types[0]] != undefined){
map.setZoom(tabZoom[results[0].types[0]]);
} else {
map.zetZoom(10);
}
//cut
Is there other solution? (Or anything from Google Map API that I don't know yet?)
Thanks!
use GLatLngBounds class
an example:
// map: an instance of GMap2
// latlng: an array of instances of GLatLng
var latlngbounds = new GLatLngBounds( );
for ( var i = 0; i < latlng.length; i++ )
{
latlngbounds.extend( latlng[ i ] );
}
map.setCenter( latlngbounds.getCenter( ), map.getBoundsZoomLevel( latlngbounds ) );
^
The trick is to add the list of all points that need to be visible on the map simultaneously into a GLatLngBounds object. The Google Maps API can do the rest of the maths.
or in v3 you can use LatLngBounds class (similar to GLatLngBounds in v2), link: http://code.google.com/apis/maps/documentation/javascript/reference.html#LatLngBounds
for an example
better check this out: http://unicornless.com/code/google-maps-v3-auto-zoom-and-auto-center
use viewport of the result geometry. if your search result does not have specific bounds, you will get an error with geometry.bounds
viewport gives you best view for the result.
map.fitBounds(results[0].geometry.viewport);
Related
I have developed an application a while ago using GE plugin. In that application, I use the Geocode function which depends of course on (maps, 2.xx). With the deprecation of Google Maps V2, this part of the code is no longer working. My code is based on the sample application for geocoding in the Google Earth Demo site (http://earth-api-samples.googlecode.com/svn/trunk/examples/geocoder.html) which no longer works either.
I searched the v3 site but couldn't find a way of dealing with this. Using
google.load("maps", "3.xx");
instead of
google.load("maps", "2.xx");
simply doesn't work and I get a rejection from the Google Maps server.
The reason using google.load("maps", "3.xx"); doesn't work is that you MUST supply the sensor parameter. i.e. google.load('maps','3.6', { other_params: 'sensor=false' });
The sensor parameter of the URL must be included, and indicates
whether this application uses a sensor (such as a GPS locator) to
determine the user's location. We've left this example as a variable
set_to_true_or_false to emphasize that you must set this value to
either true or false explicitly.
See: https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API
Anyhow, I made a working example of using the Google Maps V3 Geocoder with the Earth Api for you to see how it works.
Also here is a code example that geocodes the term "New York" and moves to the first result found once the plugin and maps api have loaded (just in case jsfiddle disappears in future...)
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('earth', '1');
google.load('maps','3.6', { other_params: 'sensor=false' }); // or true
var ge = null; // GEPlugin
var geocoder = null; // GClientGeocoder
var init = function() {
google.earth.createInstance('map3d', initCallback, failureCallback);
};
var initCallback = function(object) {
ge = object;
geocoder = new window.google.maps.Geocoder(); //v3 Geocoder
ge.getWindow().setVisibility(true);
// for example: geocode New York
geocode("New York");
};
var failureCallback = function(error) {
alert("Plugin Error: " + error);
};
var geocode = function(address) {
geocoder.geocode({ 'address': address }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
// do something with the result, such as flying to it...
var point = results[0].geometry.location;
var lookat = ge.createLookAt('');
lookat.set(point.lat(), point.lng(), 100, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 0, 1000);
ge.getView().setAbstractView(lookat);
} else {
alert("Geocode Error: " + status);
}
});
};
google.setOnLoadCallback(init);
</script>
You could load the v3 script and modify the geocoding parts of your project, but if all you need is geocoding you can call the Geocoding web service directly.
Or, you can keep your existing code: Most old v2 code actually still works, it's just that GLatLng.x and y were never supported. So instead of point.x and point.y, use point.lng() and point.lat() respectively.
I have successfully set up a Leaflet JS map that uses the Google maps geocoder to pan to a geocoded address. But I am also trying to use "map.fitBounds" to get the appropriate zoom level from the Viewport, but it does not seem to be working. The code I am using is:
map.panTo([results[0].geometry.location.lat(),results[0].geometry.location.lng()]);
map.fitBounds([[results[0].geometry.viewport.southwest.lat(), results[0].geometry.viewport.southwest.lng()],[results[0].geometry.viewport.northeast.lat(), results[0].geometry.viewport.northeast.lng()]]);
See example here: http://chrismccreath.hostzi.com/geocode_test.html
How can I fix it so that it zooms to the appropriate viewport returned by the google maps geocoder result?
There are no properties like results[0].geometry.viewport.southwest/northeast(I guess you were watching at the network-traffic inside the console, but what you see there will not be passed to the callback-function directly). To get the southwest/northeast use the methods getSouthWest() and getNorthEast() of google.maps.LatLngBounds .
results[0].geometry.viewport is a google.maps.LatLngBounds-object, but you can't use it directly in Leaflet.
You must "convert" it to an array or an Leaflet.LatLngBounds-object.
This should work:
map.fitBounds([
[results[0].geometry.viewport.getSouthWest().lat(),
results[0].geometry.viewport.getSouthWest().lng()],
[results[0].geometry.viewport.getNorthEast().lat(),
results[0].geometry.viewport.getNorthEast().lng()]
]);
Thanks for posting the working example. It helped a lot. It didn't work immediately for me however, had to do some tweaking for it to work.
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( {'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0].geometry.viewport) {
map.fitBounds([[results[0].geometry.viewport.getSouthWest().lat(),
results[0].geometry.viewport.getSouthWest().lng()],
[results[0].geometry.viewport.getNorthEast().lat(),
results[0].geometry.viewport.getNorthEast().lng()]]);
map.setZoom(18);
} else if (results[0].geometry.bounds) {
map.fitBounds([[results[0].geometry.bounds.getSouthWest().lat(),
results[0].geometry.bounds.getSouthWest().lng()],
[results[0].geometry.bounds.getNorthEast().lat(),
results[0].geometry.bounds.getNorthEast().lng()]]);
} else { // give up, pick an arbitrary zoom level
map.panTo(results[0].geometry.location);
map.setZoom(15);
}
} else {
$('#result').html('Geocode was not successful for the following reason: ' + status);
}
});
}
Just thought I'd post it if anybody else wasn't able to figure out how to get it to work.
Thanks again!
DrMolle pointed out that leaflet map objects are not Google Maps API v3 objects (in the other question you reference). This works:
map.panTo([results[0].geometry.location.lat(),results[0].geometry.location.lng()]);
map.fitBounds([[results[0].geometry.viewport.getNorthEast()],
[results[0].geometry.viewport.getSouthWest()]]);
working example
As described in the documentation:
results[].geometry.location is a google.maps.LatLng, which panTo requires as an argument.
results[].geometry.viewport is a google.maps.LatLngBounds, which fitBounds requires as an argument.
I tried to search for all cities within a visible map's bounds. How can I do that?
Below is what I tried to do:
$.fn.gmap3.geocoder.geocode({ 'address': 'Georgia' }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['locality']
};
service.search(request, function (results, status) {
debugger;
});
}
});
But the result is ZERO_RESULTS. Maybe the reason is that the results are restricted to a radius of 50.000 meters?
Anyone knows how to solve my problem? Thanks a lot.
--UPDATE--
Thank, Sean, for reading my post carefully and give detail feedback.
This is how I refer to the lib:
src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
I also added more detail to the geocode function to get more precise result. But I still don't get the results I want.
Check the list in this page: https://developers.google.com/places/documentation/supported_types, I realize that almost all items in the first list returns values but not for the second list. The only item return value is 'political' and it returns only 1 instead of 20.
This is my code after modifing:
this.setCenterByAddress = function (address, region) {
$.fn.gmap3.geocoder.geocode({ 'address': address, 'region': region }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['country',
'administrative_area_level_1',
'administrative_area_level_2',
'administrative_area_level_3',
'colloquial_area',
'country',
'floor',
'geocode',
'intersection',
'locality',
'natural_feature',
'neighborhood',
'political',
'point_of_interest',
'post_box',
'postal_code',
'postal_code_prefix',
'postal_town',
'premise',
'room',
'route',
'street_address',
'street_number',
'sublocality',
'sublocality_level_4',
'sublocality_level_5',
'sublocality_level_3',
'sublocality_level_2',
'sublocality_level_1',
'subpremise',
'transit_station']
};
service.search(request, function (results, status) {
debugger;
});
}
});
}
MORE INFO: The same value return even when location and radius is used. And I use free map and receive "OVER_QUERY_LIMIT" all the time.
You shouldn't be limited to 50,000 meters unless you use the location and radius option, which you are not; you are using bounds. I suggest backing out a level and digging into the results that are returned from the starting call to geocode, because your usage of the PlacesService appears to be correct. What are the values internal to the resultBounds object? I also notice that you aren't using region biasing when you call the geocoder and it may be that "Georgia" is not sufficiently specific. For example, do you mean the region within the Russian Federation or the US state? And I'm not sure what URL you are using to load the Google Maps API & places library, but that could also be effecting your results.
I'd double-check the results coming back from the geocoder, because unless I am missing something, it looks like your basic approach is sound.
You can't return more than two near by localities around a particular latitude-longitude with Geocoding API/Places API
Please see this thread on Google Places API forum
This is not possible with the Google Places API as political results
such as locality, neighbourhood and sublocality are returned to
identify the area of the request and are limited to two per request.
I want to remove an individual marker from Google map. I am using version 3 API. I know how I can remove all the markers by maintaining a markerArray and setting map null for all.
For removing one by one, I am thinking to make a key value pair combination. So that I give a key and remove the particular marker. I need help over this.
Following is the code, that I use to dram marker:
function geoCodeAddresses(data) {
var markerInfo = {addressKey: '', marker:''};
for (var i = 0; i < data.length; i++) {
myLocation = data[i];
geocoder.geocode({"address":myLocation}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({map:map, position:results[0].geometry.location});
// checkpoint A
alert(myLocation);
/*
markerInfo.addressKey = myLocation;
markerInfo.marker = marker;*/
//mArray.push(markerInfo);
}
});
}
}
I will search for addresskey and remove the marker from mArray. But I get last value every time in geocode callback method. And one object got pushed every time. the var myLocation always give me the address of the last index of my array. If I alert it at check point A.
My approach is right?
Your problem is this line:
mArray.push(markerInfo);
That doesn't push the values of markerInfo into your array. It pushes a reference to markerInfo into your array. Now, on your next iteration of the loop, when you change the value of markerInfo, it changes the value pointed at by the references in the array too. So your array ends up having elements that all have the same value.
Try this instead:
mArray.push({addressKey:myLocation,marker:marker});
If that doesn't work, then this:
mArray.push({addressKey:data[i],marker:marker});
This question already has an answer here:
google maps api v3 - nearest streetview
(1 answer)
Closed 9 years ago.
I'm using ipinfodb.com for a while to get the Latitude and Longitude from the user IP to view the google streetview. But recently ipinfodb has changed their database, and most the latitude/longitude values are changed, because of which I dont get the streetview.
I'm using "Google Maps Javascript API V3 Services" but not sure on how to the next and nearest possible GoogleStreetview. Could you please suggest.
Regards
The API has a getPanoramaByLocation method in StreetViewService Class
Below is an example of how to get a streetview within a given radius around the given latLng position, note that if the radius is less than 50 meters the nearest panorama will be returned
var streetViewService = new google.maps.StreetViewService();
streetViewService.getPanoramaByLocation(latLng, radius, function(data, status)
{
if (status == google.maps.StreetViewStatus.OK)
{
var nearStreetViewLocation = data.location.latLng;
//...
}
});
radius doesn't guarantee the closest street view point. For example: if the view point is 10m away but you define your radius as 1000 then the closest isn't selected. So if you have several points (some really close, some really far) then I would still use iteration:
var streetViewService = new google.maps.StreetViewService();
var radius = 10;
streetViewService.getPanoramaByLocation(latLng, radius, handler);
function handler(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var nearStreetViewLocation = data.location.latLng;
//...
} else {
radius += 50;
streetViewService.getPanoramaByLocation(latLng, radius, handler);
}
};