I am using the Google Maps API v.3 to create a google map with directions very similar to this example by google.
The main difference is that on page load, the google map canvas is set to 100%, and when the user requests directions the map is reduced to 70% (to make room for the directions panel)
When the user gets directions, the directions are displayed as if the map canvas was at 100%, not 70%, essentially cutting off part of the directions. I need the map to reorient / recenter when the direction response is displayed.
You can demo this out here: http://j2designpartnership.com/directions/
When the user types in directions, this function is called: calcRoute()
function calcRoute() {
if (document.getElementById("start").value != "") {
activeSettings();
}
else{
defaultSettings();
}
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
var request = {
origin:start,
destination:end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
//make the request for our directions
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
var recenter = new google.maps.LatLng(40.440625,-79.995886);
map.setCenter(recenter);
}
The part to pay attention to here is the top conditional that basically changes the width of the map canvas if there is text in the input field.
How do I recenter the map now that the map canvas is smaller?
When the map div changes size trigger the resize event on the map as specified in the documentation
resize | None | Developers should trigger this event on the map when the div changes size:
google.maps.event.trigger(map, 'resize') .
Related
I'm trying to integrate the Google maps API to my page. I use a code that extract the locations from JSON and saves the location in an array, then return the place-data of each location. Everything went well except I can't activate the infowindow function when clicking on marker on the map. This is the error that appears when clicking:
var map; // declares a global map variable
/*
Start here! initializeMap() is called when page is loaded.
*/
function initializeMap() {
var locations;
var mapOptions = {
disableDefaultUI: true
};
/*
For the map to be displayed, the googleMap var must be
appended to #mapDiv in resumeBuilder.js.
*/
map = new google.maps.Map(document.querySelector('#map'), mapOptions);
/*
locationFinder() returns an array of every location string from the JSONs
written for bio, education, and work.
*/
function locationFinder() {
// initializes an empty array
var locations = [];
// adds the single location property from bio to the locations array
locations.push(bio.contacts.location);
// iterates through school locations and appends each location to
// the locations array. Note that forEach is used for array iteration
// as described in the Udacity FEND Style Guide:
// https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
education.schools.forEach(function(school){
locations.push(school.location);
});
// iterates through work locations and appends each location to
// the locations array. Note that forEach is used for array iteration
// as described in the Udacity FEND Style Guide:
// https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
work.jobs.forEach(function(job){
locations.push(job.location);
});
return locations;
}
/*
createMapMarker(placeData) reads Google Places search results to create map pins.
placeData is the object returned from search results containing information
about a single location.
*/
function createMapMarker(placeData) {
// The next lines save location data from the search result object to local variables
var lat = placeData.geometry.location.lat(); // latitude from the place service
var lng = placeData.geometry.location.lng(); // longitude from the place service
var name = placeData.formatted_address; // name of the place from the place service
var bounds = window.mapBounds; // current boundaries of the map window
// infoWindows are the little helper windows that open when you click
// or hover over a pin on a map. They usually contain more information
// about a location.
var infoWindow = new google.maps.InfoWindow({
content: name
});
// marker is an object with additional data about the pin for a single location
var marker = new google.maps.Marker({
map: map,
position: placeData.geometry.location,
title: name
});
// hmmmm, I wonder what this is about...
marker.addListener('click', function() {
// your code goes here!
infowindow.open(map, marker);
});
// this is where the pin actually gets added to the map.
// bounds.extend() takes in a map location object
bounds.extend(new google.maps.LatLng(lat, lng));
// fit the map to the new marker
map.fitBounds(bounds);
// center the map
map.setCenter(bounds.getCenter());
}
/*
callback(results, status) makes sure the search returned results for a location.
If so, it creates a new map marker for that location.
*/
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
createMapMarker(results[0]);
}
}
/*
pinPoster(locations) takes in the array of locations created by locationFinder()
and fires off Google place searches for each location
*/
function pinPoster(locations) {
// creates a Google place search service object. PlacesService does the work of
// actually searching for location data.
var service = new google.maps.places.PlacesService(map);
// Iterates through the array of locations, creates a search object for each location
locations.forEach(function(place){
// the search request object
var request = {
query: place
};
// Actually searches the Google Maps API for location data and runs the callback
// function with the search results after each search.
service.textSearch(request, callback);
});
}
// Sets the boundaries of the map based on pin locations
window.mapBounds = new google.maps.LatLngBounds();
// locations is an array of location strings returned from locationFinder()
locations = locationFinder();
// pinPoster(locations) creates pins on the map for each location in
// the locations array
pinPoster(locations);
}
/*
Uncomment the code below when you're ready to implement a Google Map!
*/
// Calls the initializeMap() function when the page loads
window.addEventListener('load', initializeMap);
// Vanilla JS way to listen for resizing of the window
// and adjust map bounds
window.addEventListener('resize', function(e) {
// Make sure the map bounds get updated on page resize
map.fitBounds(mapBounds);
});
You are trying to create an infoWindow object here:
// infoWindows are the little helper windows that open when you click
// or hover over a pin on a map. They usually contain more information
// about a location.
var infoWindow = new google.maps.InfoWindow({
content: name
});
and then work with it (show message after marker click)
// hmmmm, I wonder what this is about...
marker.addListener('click', function() {
// your code goes here!
infowindow.open(map, marker);
});
But look at your variables attentively:
infoWindow !== infowindow (letter W)
browser doesn't know, what infowindow is, and falls with an error.
Read more about variables naming in JS here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Declarations
I came across this question while trying to debug some code that I had copied from the Udacity tutorial (Getting Started with the APIs) that Hasam was drawing from. My code, as copied from the video itself, lacked some key lines, and wouldn't run correctly. The tutorial's 'resources' didn't have a copy of the code. I eventually found a good copy of the code on Github: https://github.com/udacity/ud864. As I wrote this answer, I found the same link tucked away on the bottom of some of the Udacity tutorial pages themselves.
I am trying the following out, based on the example from GoogleMapsv3APIExample:
I have a route from A to B with some markers:
I modify the route by dragging "a transitional waypoint" (shown by a white circle)
I want the markers to be updated to the new route
I adapted the linked example in this gist:
on lines 37-39 I add a listener for the directions_changed event
in recalculateMarkers, I set all markers to null and place them again on the map
it seems that directionsDisplay.directions still contains the old route (before dragging)
the result I get is this:
Any suggestions ?
Thanks!
Problem is in directions_changed event: This event is fired when the rendered directions change, either when a new DirectionsResult is set or when the user finishes dragging a change to the directions path.
When calcRoute() finishes there are two sets of markers created: one from recalculateMarkers() and the other from calcRoute().
Event listener has to be moved to calcRoute() and to be set up in case of route success:
function calcRoute() {
var request = {
origin: 'Sydney, NSW',
destination: 'Broken Hill, NSW',
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
showSteps(response);
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
console.log('directions_changed');
recalculateMarkers();
});
}
});
}
See example at jsbin.
Here is my fiddle . Here i have displayed current location and end location by balloons.
And i am trying to put directions between start and end point in the map. In this case no markers for the directions are displayed may be because both shares common location. But the zoom is too great , results in it is not covering start and end point. User have to make double right click to see both start and location.
I have also tried,
new_boundary = new google.maps.LatLngBounds();
new_boundary.extend(new google.maps.LatLng(start));
new_boundary.extend(new google.maps.LatLng(end));
map.fitBounds(new_boundary);
But it is not working. Whats wrong with my map configuration ?
your script breaks (at least for me) at this line:
dir=((Math.atan2(z.lng()-a.lng(),z.lat()-a.lat())*180)/Math.PI)+360
take a look at this line:
z=(step.lat_lngs.length)?step.lat_lngs[1]:step.end_point,
for the first step lat_lngs.length is 1 , so step.lat_lngs[1] is undefined, the call of z.lng() fails with "Cannot call method 'lng' of undefined"
Possible fix for that error:
z=(step.lat_lngs.length>1)?step.lat_lngs[step.lat_lngs.length-1]:step.end_point,
Related to the zoom:
When you wouldn't have disabled the complete UI you would have seen that the result (zoom ) is correct.
The DirectionsRenderer by default will refresh the viewport of the map so that the complete route is visible.
This will be done(the bounds initally set in your script will be discarded).
To have another result(preserve the current viewport, but extend it that also the route is visible), you must:
set the preserveViewPort-option of the DirectionsRenderer to true(default is false)
extend the bounds of the map with the bounds of the route
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.set('preserveViewport',true);
map.fitBounds(map.getBounds().union(response.routes[0].bounds));
//continue with your code
This code is correct for example
Your map change resolution when you add
directionsDisplay.setDirections(response);
setDirections(directions:DirectionsResult) None Set the renderer to
use the result from the DirectionsService. Setting a valid set of
directions in this manner will display the directions on the
renderer's designated map and panel.
Hope, that i understand problem right, English i not my native language
Try to add validation as
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
if(!response.routes[0].bounds.getNorthEast().equals(response.routes[0].bounds.getSouthWest())){
directionsDisplay.setDirections(response);
}
addDirections(response.routes[0]);
}
});
To check if answer contains different point
I am using the Google Maps api to create a small, stripped down map that shows a geocoded location with a marker. You can see the live code here: http://www.ddbeadworks.com/
It works flawlessly, until someone clicks the Google logo to take themselves to maps.google.com. There, the map is properly zoomed and centered on the location, but the marker isn't being passed to maps.google.com, it seems, as that doesn't appear? I looked through the API, but I can't find anything like "markersToGoogle boolean" or any such variable.
Here is the relevant code section. This is the only place I deal with markers anywhere. JavaScript:
var address = $(this).attr("name");
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
if (status == google.maps.GeocoderStatus.OK)
{
var yourStartLatLng = new google.maps.LatLng(lat, lng);
$('#map_canvas').gmap('addMarker', {'position': yourStartLatLng, 'bounds': true});
$('#map_canvas').gmap('option', 'zoom', 14)
$('#map_canvas').gmap('option', 'disableDefaultUI', true)
}
});//close geocoder
That is what the Google logo links to, the main Google Maps web site, with the same center and zoom as the map it came from.
If you want to make a bigger map with your marker on it, you need to link to a bigger Google Maps API v3 based map (and not expect your user to use the "Google" logo).
Have developed an app in Sencha Touch V2.This app contains a Mappa panel where there is a map, this map has been populated with markers which corresponds to the various locations(cafes) that are taken from a json file.
The App Map panel functions as follows:
On a marker click the start and end locations textields pops ups, where the user enters the values for the start and end locations, another click to any of the other markers results in, the directions from start and end locations being plotted onto the map.
We need to implement the following functionality:
We need to facilitate the directions of locations entered in google maps plotted onto the map on a button click and also need to recreate the map instance(refresh map) and place existing markers on another button click(map clear button) so as to create a new instance for the user to find directions for different start and end locations.
Problems that we have are:
While defining the handler for the button click resulted in no action being performed(getting directions handler was not functioning).
Inorder to recreate the instance of the map, we had set the map to null but that resulted in a map without markers.
Could anyone please help out in accomplishing the tasks for this app in Sencha touch version 2.
Created this kind of application / functionality long time back.
You can create a floating formpanel and provide the field entries there for source and destination end points.
Then, you could write the below code on tap of "Get Directions" button,
Code snippet :-
tap: function() {
var src = Ext.getCmp('srcField');
var destn = Ext.getCmp('destField');
var mode = Ext.getCmp('travelMode');
var request = {
origin: src.getValue(),
destination: destn.getValue(),
travelMode: mode.getPressedButtons()[0].getText(),
};
Ext.Ajax.request({
url: 'http://maps.googleapis.com/maps/api/directions/json?origin='+src.getValue()+'&destination='+destn.getValue()+'&mode='+mode.getPressedButtons()[0].getText()+'&sensor=false';
method:'post',
success : function(response) {
showDirections(response,request);
}
});
function showDirections(res,req) {
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
var map = Ext.getCmp('googleMapComponentId').getMap();
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
directionsDisplay.setMap(map);
}
});
}