We're trying to build an app that allows users to view places around their current location.
You can see the Google Maps API & the Google Places Library functioning here, but not as one: http://www.blazingsasquatch.com/geo/index4.html
You'll notice the button "show me my loc" pulls your current location and the map is showing an arbitrary location in Boston with places nearby.
We've created variables for both the longitude and latitude and we've attempted to pass those variables directly into the "pyrmont" location variable but we've had no luck.
Initially we tried setting the "pyrmont" location using following, also with no luck:
google.maps.LatLng(position.coords.latitude, position.coords.longitude);
So how can we get the current location populated?
var pyrmont = new google.maps.LatLng("CURRENT LOCATION HERE");
Will it accept a variable or an integer only?
initialize will be called before the callback of navigator.geolocation.getCurrentPosition() , so you cannot use the result in initialize() .(you may view getCurrentPosition as a asynchronous request)
Invoke the action(creation of the marker and places-request) inside the callback of getCurrentPosition()
See a working demo: http://jsfiddle.net/doktormolle/C5ZtK/
The LatLng constructor takes two floating point numbers, like so:
pos = new google.maps.LatLng(-34.397, 150.644);
After reviewing the source code, it seems the problem is another one: the anonymous callback function you are passing to getCurrentPosition() is called when the geographic location is found, which can take some time (especially using GPS and such). initialize() is called when the page is loaded, which is sooner, so place is not set at this time (besides, it's not visible in initialize() since it's not a global variable, but never mind that). So you have to move the stuff you're currently doing in initialize() to the callback function you are passing to getCurrentPosition(). Then, you can use
var pyrmont = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
Related
I use AutocompleteService.getPlacePredictions method to get autocomplete items for my drop down. Very often that method returns "long" placeIds that look like this (actual placeId):
ChIJx55rzdwQ9YgRHB-NARRWZyuaBjAxNzExIERvbm5hIEx5bm4gRHJpdmUsIFNteXJuYSwgR0EsIFVuaXRlZCBTdGF0ZXM
If I then try to pass that place ID to Geocoder I get status of ZERO_RESULTS and no places:
new google.maps.Geocoder().geocode(
{ placeId: "thatLongPlaceId"},
function (results, status) { /* no place data returned */ });
But at the same time if I make the following GET call the same placeId returns the expected address:
https://maps.googleapis.com/maps/api/place/details/json?key=MyApiKey&placeid=ChIJx55rzdwQ9YgRHB-NARRWZyuaBjAxNzExIERvbm5hIEx5bm4gRHJpdmUsIFNteXJuYSwgR0EsIFVuaXRlZCBTdGF0ZXM
What am I doing wrong? What's the proper way of using that long place ID to get place data?
I think the autocomplete endpoint is not returning valid placeids as of today or yesterday. I'm running into a similar problem.
See Google Place Autocomplete API returning wrong place id
The ZERO_RESULTS problem isn't because of the long place ids. To see this, try using the (long) place id from an autocomplete result for an address in Sydney, for e.g.
ChIJr-__yjeuEmsR3RMEBNOoUn-aBjQ0OCBQaXJyYW1hIFJvYWQsIFB5cm1vbnQsIE5ldyBTb3V0aCBXYWxlcywgQXVzdHJhbGlh
The call to Geocoder.geocode should return 1 result.
Long story short, the Geocoding API (that google.maps.Geocoder uses) hasn't been fixed for the problem in https://code.google.com/p/gmaps-api-issues/issues/detail?id=11107.
I'm working on a site that will use the Google Maps / Places APIs. I have verified that my API key is working fine, so that's not an issue. I just can't even get the map to display - that's my issue.
I've copied the example exactly, and it still won't work.
Here's my code in a gist because it's a few files. It should be runnable, that's all the content.
What I've tried so far:
- Putting it all in a document ready function (jQuery).
- Taking it out of the getCurrentPosition function so it was just out in the main.js file.
- Moving the position of the script link in my HTML file, nothing changed at any position.
- If I console.log() the lat and long variables, they print my location. But they're "undefined" when I type them into Chrome Dev Tools console. However, my "map" variable prints the map div to console.
- Using static coords, rather than coords gathered from the navigator HTML5 element.
- Setting height and width for the map div with pixels, percent, and vh/vw. It's taking the screen - I know because I gave it a background color that is showing.
- Added parameters to the end of my API load: &callback=initialize&libraries=places
This is my first time using Maps, so I'm totally lost here. I followed Google's example to a tee, and still nothing.
WebStorm is underlining all of the google.maps.x classes and saying they're "unresolved variables or types". That may be my problem, but I don't know what causes that or how to fix it. And to be clear, I have looked through every article I could find on Stack Overflow related to this, and haven't found a solution.
UPDATE:
- I just tried copying and pasting this example from Google exactly as it appears (with my API key, of course), and it still didn't work. I put it in script tags in my HTML. The only way it works is if I delete the initMap() function - not the contents of it, just the declaration of it as a function. So why is the scope acting so weird here? It's treating everything inside of the function (which is in a script tag in my HTML) as if it's all undefined just because it's in a function... at the highest scope level.
You are trying to run main.js before the Google Maps SDK has loaded. Move it above main.js' inindex.html`:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=MY_KEY&libraries=places"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
Then, remove the initialize function:
if ("geolocation" in navigator) {
console.log("Geolocation is enabled.");
navigator.geolocation.getCurrentPosition(function (position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
var map;
var service;
var infoWindow;
console.log("lat: " + lat);
//Initialize Google Map. Starts at user's location.
var userLocation = new google.maps.LatLng(lat, long);
map = new google.maps.Map(document.getElementById('map'), {
center: userLocation,
zoom: 15
});
var request = {
location: userLocation,
radius: '500',
types: ['store']
};
service = new google.maps.places.PlaceService(map);
service.nearbySearch(request, callback);
//Callback function for nearbySearch
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
var place = results[i];
createMarker(results[i]);
}
}
}
});
} else {
console.log("Geolocation is disabled.");
//Inform user why we use location
//Allow user to enter location manually
}
That works for me.
Without any knowledge of JS, I was forced to implement a map (OSM via Leaflet) on a webpage. On this map, there should be a marker for the actual address of a person. The address is saved as a string in the database.
I can see a map, can add marker to it, but after that, I'm lost.
I've tested some Leaflet-geocoding-plugins, but i must confess, that they're not simple enough for my actual programmming experience.
Another question was about the same problem, but i didn't understand, how to get the lon/lat from an address with the L.Geosearch-plugin for Leaflet.
Can anyone provide me a example of looking up an address (via OSMN or something else, not google/bing or other api-key-needy provider), converting it to lon/lat and add a marker to it on a map?
First you will have to include the .js files of a geocoder in the head of your HTML code, for my example I have used this one: https://github.com/perliedman/leaflet-control-geocoder. Like this:
<script src="Control.Geocoder.js"></script>
Then you will have to initialize the Geocoder in your .js:
geocoder = new L.Control.Geocoder.Nominatim();
Then you will have to specify the address that you are looking for, you can save it in a variable. For example:
var yourQuery = (Addres of person);
(You can also get the address out of your database, then save it in the variable)
Then you can use the following code to 'geocode' your address into latitude / longitude. This function will return the latitude / longitude of the address. You can save the latitude / longitude in an variable so you can use it later for your marker. Then you only have to add the marker to the map.
geocoder.geocode(yourQuery, function(results) {
latLng= new L.LatLng(results[0].center.lat, results[0].center.lng);
marker = new L.Marker (latLng);
map.addlayer(marker);
});
I made a jfsfiddle that
Has an address set
Looks for the coordinates of that address using geosearch
Creates a marker at the coordinates of that address found by geosearch.
It can be found here: https://jsfiddle.net/Alechan/L6s4nfwg/
The "tricky" part is dealing with the Javascript "Promise" instance returned by geosearch and that the address may be ambigous and more than one coordinate may be returned in that case. Also, be careful because the first position in the Leaflet coordinates corresponds to the latitude and the second to the longitude, which is in reverse of the Geosearch "x" and "y" results.
Geosearch returns a promise because it's an asynchronous call. The alternative would have to be a synchronous call and the browser would have to be freezed until an answer was retrieved. More info about promises from MDM (Mozilla) and Google.
In my example, I create a marker for every result found for the indicated address. However, in this case the address is unambiguous and returns only one result.
Breakdown of code:
<!-- Head, imports of Leaflet CSS and JS, Geosearch JS, etc -->
<div id='map'></div>
<script>
// Initialize map to specified coordinates
var map = L.map( 'map', {
center: [ 51.5, -0.1], // CAREFULL!!! The first position corresponds to the lat (y) and the second to the lon (x)
zoom: 12
});
// Add tiles (streets, etc)
L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap',
subdomains: ['a','b','c']
}).addTo( map );
var query_addr = "99 Southwark St, London SE1 0JF, UK";
// Get the provider, in this case the OpenStreetMap (OSM) provider.
const provider = new window.GeoSearch.OpenStreetMapProvider()
// Query for the address
var query_promise = provider.search({ query: query_addr});
// Wait until we have an answer on the Promise
query_promise.then( value => {
for(i=0;i < value.length; i++){
// Success!
var x_coor = value[i].x;
var y_coor = value[i].y;
var label = value[i].label;
// Create a marker for the found coordinates
var marker = L.marker([y_coor,x_coor]).addTo(map) // CAREFULL!!! The first position corresponds to the lat (y) and the second to the lon (x)
// Add a popup to said marker with the address found by geosearch (not the one from the user)
marker.bindPopup("<b>Found location</b><br>"+label).openPopup();
};
}, reason => {
console.log(reason); // Error!
} );
</script>
Is there a way to load a map using js, but show the reference location as an actual places listing?
I'd like to load a map that shows a particular business (I have the places reference number) then display a map around it.
I would just use the iframe, but it doesn't allow for the level of customization that the js library does.
Yes. That is one of the more standard ways of using maps.
You have the lat long for the location to both center your map and drop a marker (probably a custom image of for instance the company logo).
Just follow any of the tutorials. They all show how to do this.
If you want to display a business that you have the reference number for then use the PlacesService.
You will also need to include the places library in the API url.
e.g
// I assume the map is already loaded and defined as variable called map
var placesService = new PlacesService();
placesService.getDetails({reference: placeReferenceNumber}, function(place, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
// Warning: Viewport may not always be defined
map.setBounds(place.geometry.viewport);
}
});
I'm trying to do something that I gather has been done quite a few times before, although I'm having some difficulty accomplishing it.
I have a webpage that displays three Google Maps.
For each of these google maps, I have a text box that accepts a post code / zip code, and a "get directions" button.
Clicking on each of these buttons uses the google.maps.DirectionsService object to display ONE set of directions in ONE panel centered at the bottom of the page.
My issue arises when I try to find a new route by searching again. As you can see in the image below, both routes are rendered.
I have one marker at the end which is in a markers collection.
I've read a few times now about how you can loop through this array and use marker.setMap(null) to clear this marker.
However, I can't seem to clear the actual routes after each specific search.
Has anybody had any problems with clearing markers from multiple maps?
Do you have to totally reset the map in some way?
If you have to clear markers, at what point in the lifecycle of the process should you do it so that your new journey appears after the search, but the old one is removed?
I use the same google.maps.DirectionsService object for all three Google maps, and they all call the same method to calculate directions, but passing in their own map object as a parameter.
function calcRoute(startPoint, location_arr) {
// Create a renderer for directions and bind it to the map.
var map = location_arr[LOCATION_ARR_MAP_OBJECT];
var rendererOptions = {
map: map
}
if(directionsDisplay != null) {
directionsDisplay.setMap(null);
directionsDisplay = null;
}
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById("directionsPanel"));
The gist being that if directionsDisplay != null, we not only pass null to setMap, we also nullify the whole object afterweards, and I found this fixed it.
I dont know the answer.... most likely all u need to do is depending on circumstances:
// put the codes after direction service is declared or run directionsService //
directionsDisplay.setMap(null); // clear direction from the map
directionsDisplay.setPanel(null); // clear directionpanel from the map
directionsDisplay = new google.maps.DirectionsRenderer(); // this is to render again, otherwise your route wont show for the second time searching
directionsDisplay.setMap(map); //this is to set up again
This is the only part you need:
// Clear past routes
if (directionsDisplay != null) {
directionsDisplay.setMap(null);
directionsDisplay = null;
}
This works for me
// on initiate map
// this listener is not necessary unless you use listener
google.maps.event.addListener(directionsRenderer, 'directions_changed', function () {
if(directionsRenderer.directions === null){
return;
}
// other codes
});
// on clear method
directionsRenderer.set('directions', null);