google maps displaying a route - javascript

according to google maps i can plan a route that crosses over several waypoints. It is explained here:http://code.google.com/intl/nl-NL/apis/maps/documentation/javascript/services.html#Routes
Now the api wants me to add the waypoints like this:
location: waypoints
so waypoints is an array wich i have to assign to the location: parameter but from what ive seen in the demo they fill the array with strings of the locations. What i was wondering if it was possible to pass the latitude and longitude instead of the strings?
update: this is the part where i try to create a route. i have put the same value in location throughout the entire loop for now but id doesn't work if i use variable values neither
function calcRoute() {
var waypts = [];
for (var i in owt.stores.spotStore.data.map) {
waypts.push({
location: new google.maps.LatLng(12.3, -33.6),
stopover:true
});
console.log(waypts);
}
var request = {
origin: new google.maps.LatLng(50.82788, 3.26499),
destination: new google.maps.LatLng(50.82788, 3.26499),
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
;

According to the API reference:
A DirectionsWaypoint represents a location between origin and destination through which the trip should be routed.
location LatLng|string Waypoint
location. Can be an address string or
LatLng. Optional
So creating a new Waypoint with a lat-long value should be as below
return {
location:new google.maps.LatLng(12.3, -33.6),
stopover:true
};

According to google documentation the waypoint can be either a string or a LatLng object.
http://code.google.com/apis/maps/documentation/javascript/reference.html#DirectionsWaypoint
here is an example using LatLng
<!DOCTYPE html>
<html>
<head><meta name="viewport" content="initial-scale=1.0, user-scalable=no"/><meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Directions Waypoints</title>
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript">
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var chicago = new google.maps.LatLng(-40.321, 175.54);
var myOptions = {
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: chicago
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
directionsDisplay.setMap(map);
calcRoute();
}
function calcRoute() {
var waypts = [];
stop = new google.maps.LatLng(-39.419, 175.57)
waypts.push({
location:stop,
stopover:true});
start = new google.maps.LatLng(-40.321, 175.54);
end = new google.maps.LatLng(-38.942, 175.76);
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.DirectionsTravelMode.WALKING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var route = response.routes[0];
}
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:70%;height:80%;">
</div>
<br />
<div>
</div>
</body>
</html>

The way points can be either a string or a latlng.
http://code.google.com/intl/nl-NL/apis/maps/documentation/javascript/services.html#Directions
In particular:
waypoints[] (optional) specifies an
array of DirectionsWaypoints.
Waypoints alter a route by routing it
through the specified location(s). A
waypoint is specified as an object
literal with fields shown below:
location specifies the location of the waypoint, either as a LatLng or as
a String which will be geocoded.
stopover is a boolean which indicates that the waypoint is a stop
on the route, which has the effect of
splitting the route into two routes.
(For more information on waypoints,
see Using Waypoints in Routes below.)
EDIT
Your way points are not valid for routing, i.e. they are in water - try centering a map on (12, -33.6).
Here's a sample using way points (not the prettiest code, but it's an example ;) ).
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript">
var myRouter = {
map_: null,
directionsHelper_: null,
stores: [
{name: "store1", location: new google.maps.LatLng(50.82788, 3.76499)},
{name: "store2", location: new google.maps.LatLng(51.02788, 3.9)}
],
calcRoute: function() {
var waypts = [];
for (var i in this.stores) {
waypts.push({
location: this.stores[i].location,
stopover:true
});
}
var request = {
origin: new google.maps.LatLng(50.82788, 3.26499),
destination: "Antwerp",
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
var _SELF = this;
this.directionsHelper_.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
_SELF.directionsDisplay_.setDirections(response);
return;
}
console.log('Directions Status: ' + status);
});
},
init: function(mapid) {
this.directionsHelper_ = new google.maps.DirectionsService();
this.directionsDisplay_ = new google.maps.DirectionsRenderer();
var center = new google.maps.LatLng(50.82788, 3.26499);
var myOptions = {
zoom:7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: center
}
this.map_ = new google.maps.Map(document.getElementById(mapid), myOptions);
this.directionsDisplay_.setMap(this.map_);
this.calcRoute();
}
};
$(document).ready(function() {
myRouter.init('map');
});
</script>
<style type="text/css">
#map {
height: 500px;
width: 600px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>

Related

Web Worker threads for Google Maps

I am trying to use web worker threads to grab directions between multiple pairs of locations parallelly and store the text in a file in the end. Everything had gone well in the sequential approach. I am using npm live-server to display the page. But the browser just closes the page instantly after it loads and I don't even get to see what rendered or consult the console for errors. If I use 'async defer' for my script tag with the google Api in index.html, I would get the "UncaughtReferenceError: google is not defined" error. Thanks in advance guys!
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
width: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
panel {
display: block;
}
</style>
</head>
<body>
<panel></panel>
<div id="map"></div>
<script src=locations.js></script>
<script src='main.js'></script>
<script src='worker.js'></script>
<script src="https://maps.googleapis.com/maps/api/js?key=<API-KEY>&callback=initMap"></script>
</body>
</html>
Here is my main.js:
let worker = new Worker('worker.js');
worker.onmessage = function(info) {
output += info.data;
};
const container = document.querySelector('panel');
let output = ""
function initMap() {
locations.forEach( spot => {
worker.postMessage(spot);
});
download("data.txt", output, 'text/plain');
console.log("Output: " + output);
}
function download(name, text, type) {
const file = new Blob([text], {type: type});
const atag = 'Download';
container.insertAdjacentHTML('afterbegin', atag);
}
And, finally the worker.js:
let directionsService;
let directionsDisplay;
let map;
self.addEventListener('message', (e) => {
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
const mapOptions = {
center: {lat: 30, lng: -90},
zoom: 6
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
directionsDisplay.setMap(map);
let request = {
origin: 'New Orleans, LA',
destination: e.data,
travelMode: 'DRIVING',
provideRouteAlternatives: false,
drivingOptions: {
departureTime: new Date('September 7, 2018 15:00:00'),
trafficModel: 'pessimistic'
},
unitSystem: google.maps.UnitSystem.IMPERIAL
};
directionsService.route(request, (result, status) => {
if (status == 'OVER_QUERY_LIMIT') {
console.log('over');
}
if (status == 'INVALID_REQUEST'){
console.log('other status')
}
if (status == 'OK') {
var data = result["routes"][0].legs[0];
postmessage(e.data + ", " + data["distance"].text + ", " + data["duration"].text + "\n");
directionsDisplay.setDirections(result);
console.log(result);
}
});
self.close();
});
Web workers have their own scope in Javascript. This means any scripts you loaded in the scope of the web page will not be available in the scope of the web worker.
Usually you use the importScripts call to load a script. However this won't work in your case because you also try to access the DOM in the web worker. This is not possible in a web worker for a number of reason (most important would be concurrent access to a data structure which is not thread save).
Looking at your code I don't think you need a web worker to calculate the routes. Most likely the actual routing is done on one of Googles servers anyway. Since this would be async anyway you do not need to worry about blocking the UI of your web page.

Display step by step Google map Direction

sorry for my bad english.
i looking for a solution to trace a route on a google map, display progressively street names when user move and read by TTS google map instructions.. (like a GPS)
I wish to display the following instruction when the user approaches the previous instruction
My watchPosition function call geolocationSuccess function each movement, this is not a good solution
In my example i trace a route from my geolocation to Omaha beach museum Normandy France
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Geolocation and Google Maps API</title>
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
function geolocationSuccess(position) {
var destination="49.366973,-0.882042";
var userLatLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var myOptions = {
zoom : 16,
center : userLatLng,
mapTypeId : google.maps.MapTypeId.ROADMAP
};
var mapObject = new google.maps.Map(document.getElementById("map"), myOptions);
// Place the marker
new google.maps.Marker({
map: mapObject,
position: userLatLng
});
direction = new google.maps.DirectionsRenderer({
map : mapObject,
suppressMarkers : true
// panel : panel // Dom element pour afficher les instructions d'itinéraire
});
if(userLatLng && destination){
var request = {
origin : userLatLng,
destination : destination,
travelMode : google.maps.DirectionsTravelMode.DRIVING // Mode de conduite
}
var directionsService = new google.maps.DirectionsService(); // Service de calcul d'itinéraire
directionsService.route(request, function(response, status){ // Envoie de la requête pour calculer le parcours
if(status == google.maps.DirectionsStatus.OK){
direction.setDirections(response); // Trace l'itinéraire sur la carte et les différentes étapes du parcours
}
var myRoute = response.routes[0].legs[0];
for (var i = 0; i < myRoute.steps.length; i++) {
console.log(myRoute.steps[i].instructions+' -> '+myRoute.steps[i].distance.value);
}
console.log(myRoute.steps[0].instructions)
$("#route").html('Dans '+myRoute.steps[0].distance.value+' m '+myRoute.steps[0].instructions);
readbyTTS(myRoute.steps[0].instructions);
var follow = navigator.geolocation.watchPosition(function(position) {
geolocationSuccess(position);
});
});
}
}
function geolocationError(positionError) {
document.getElementById("error").innerHTML += "Error: " + positionError.message + "<br />";
}
function geolocateUser() {
// If the browser supports the Geolocation API
if (navigator.geolocation)
{
var positionOptions = {
enableHighAccuracy: true,
timeout: 10 * 1000 // 10 seconds
};
navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError, positionOptions);
}
else
document.getElementById("error").innerHTML += "Your browser doesn't support the Geolocation API";
}
window.onload = geolocateUser;
</script>
<style type="text/css">
#map {
width: 800px;
height: 600px;
}
</style>
</head>
<body>
<h1></h1>
<div id="map"></div>
<p><span id="route"></span></p>
<p id="error"></p>
</body>
</html>
Thanks for your help
KilRoy
You can try to use Google Maps Directions API, it is a service that calculates directions between locations using an HTTP request.
This service is generally designed for calculating directions for static (known in advance) addresses for placement of application content on a map; this service is not designed to respond in real time to user input.
Check this SO question for more information.

Google Maps API V3 : How to get multiple path distances using direction from a point A to point B

I can get only one driving distance from point A to point B using google map api v3.
Code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Directions Complex</title>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body style="font-family: Arial; font-size: 13px; color: red;">
<div id="map" style="width: 400px; height: 300px;"></div>
<div id="duration">Duration: </div>
<div id="distance">Distance: </div>
<script type="text/javascript">
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
var myOptions = {
zoom:7,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map"), myOptions);
directionsDisplay.setMap(map);
var st=new google.maps.LatLng(51.7519, -1.2578);
var en=new google.maps.LatLng(50.8429, -0.1313);
var request = {
origin: st,
destination:en,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
// Display the distance:
document.getElementById('distance').innerHTML +=
(response.routes[0].legs[0].distance.value)/1000 + "killo meters";
alert((response.routes[0].legs[0].distance.value)/1000 + "killo meters");
// Display the duration:
document.getElementById('duration').innerHTML +=
response.routes[0].legs[0].duration.value + " seconds";
alert( response.routes[0].legs[0].duration.value + " seconds");
directionsDisplay.setDirections(response);
}
});
</script>
</body>
</html>
But I want to get multiple or all possible driving distances using google map api v3. I want to get multiple distances like given below.
There is a provideRouteAlternatives options that can be specified with the directions request parameters to tell the DirectionsService to return multiple results. You can amend your request parameters as follows:
var request = {
origin: st,
destination: en,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
// Returns multiple routes
provideRouteAlternatives: true
};
Your event handler for obtaining the directions can be modified to create a new DirectionsRenderer for each route as follows (ensure you set the correct route index each time, otherwise the DirectionsRenderer will render the first route in the response):
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
// Create a new DirectionsRenderer for each route
for (var i = 0; i < response.routes.length; i++) {
var dr = new google.maps.DirectionsRenderer();
dr.setDirections(response);
// Tell the DirectionsRenderer which route to display
dr.setRouteIndex(i);
dr.setMap(map);
// Code ommited to display distance and duration
}
}
}
The code where you append the distance and duration will need to be brought into this for loop so it appends the distance and duration for each route. I've ommited this in the code snippet above but it is in the demo Fiddle below.
I've created a Fiddle to demonstrate this.

Google Maps how to get to show only one marker?

i've been dealing with this couple of hours and i still cant figure how to do it.
my objective is to display only one marker when searching addresses close to each other.
below you have the code i use in my html in order to search for addresses, note - i'm developing a windows application that does such, in which case you might find some missing stuff to do actions by clicking buttons since this is done via .NET windows application
html code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com.mx/maps/api/js?sensor=true&language=es"></script>
<script type="text/javascript">
var G = google.maps;
var map;
var geocoder = new G.Geocoder();
var marker;
var markersArray = [1];
function initialize() {
createMap();
geocode('Chicago');
}
function createMap() {
var myOptions = {
center: new G.LatLng(0,0),
zoom: 17,
mapTypeId: G.MapTypeId.ROADMAP
}
map = new G.Map(document.getElementById("map_canvas"), myOptions);
}
function geocode(address){
geocoder.geocode({ 'address': (address ? address : "Miami Beach, Florida")}, function (results, status) {
if (status == G.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
marker = new G.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: results[0].geometry.location
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
reading previous posts i know that if/else statement has to be used but cant get it right.
your help is very appreciated.
Leo P.
You can add a small bit of code to the beginning of your Geocode function that will remove the previous marker before setting a new one. Try this:
function geocode(address){
if (marker) {
marker.setMap(null);
}
geocoder.geocode({ 'address': (address ? address : "Miami Beach, Florida")}, function (results, status) {
Create only one marker as a global variable and change its position as needed. Like that you also save memory because you're not creating a new marker object on each request:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style>
html, body {width:100%; height:100%}
</style>
<script type="text/javascript" src="http://maps.google.com.mx/maps/api/js?sensor=true&language=es"></script>
<script type="text/javascript">
var G = google.maps;
var map;
var marker;
var geocoder = new G.Geocoder();
function initialize() {
createMap();
geocode('Chicago');
}
function createMap() {
var myOptions = {
center: new G.LatLng(0,0),
zoom: 17,
mapTypeId: G.MapTypeId.ROADMAP
}
map = new G.Map(document.getElementById("map_canvas"), myOptions);
// Create a single marker, (global variable), and don't give it a position just yet.
marker = new G.Marker({
map: map,
animation: google.maps.Animation.DROP,
});
}
function geocode(address){
geocoder.geocode({ 'address': (address ? address : "Miami Beach, Florida")}, function (results, status) {
if (status == G.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
//Position the marker
marker.setPosition(results[0].geometry.location);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>

Loading city/state from SQL Server to Google Maps?

I'm trying to make a small application that takes a city & state and geocodes that address to a lat/long location. Right now I am utilizing Google Map's API, ColdFusion, and SQL Server. Basically the city and state fields are in a database table and I want to take those locations and get marker put on a Google Map showing where they are.
This is my code to do the geocoding, and viewing the source of the page shows that it is correctly looping through my query and placing a location ("Omaha, NE") in the address field, but no marker, or map for that matter, is showing up on the page:
function codeAddress() {
<cfloop query="GetLocations">
var address = document.getElementById(<cfoutput>#Trim(hometown)#,#Trim(state)#</cfoutput>).value;
if (geocoder) {
geocoder.geocode( {<cfoutput>#Trim(hometown)#,#Trim(state)#</cfoutput>: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: <cfoutput>#Trim(hometown)#,#Trim(state)#</cfoutput>
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
</cfloop> }
And here is the code to initialize the map:
var geocoder;
var map;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(42.4167,-90.4290);
var myOptions = {
zoom: 5,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: "Test"
});
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
I do have a map working that uses lat/long that was hard coded into the database table, but I want to be able to just use the city/state and convert that to a lat/long. Any suggestions or direction? Storing the lat/long in the database is also possible, but I don't know how to do that within SQL.
You may want to consider the following example:
Using the V2 API:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps API Geocoding Demo</title>
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false"
type="text/javascript"></script>
</head>
<body onunload="GUnload()">
<div id="map_canvas" style="width: 400px; height: 300px"></div>
<script type="text/javascript">
// Prepare this list from ColdFusion
var locations = [
'New York, NY',
'Los Angeles, CA',
'Chicago, IL',
'Houston, TX',
'Phoenix, AZ'
];
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map_canvas"));
var geocoder = new GClientGeocoder();
var index = 0;
var geocoderFunction = function () {
geocoder.getLatLng(locations[index], function (point) {
if (point) {
map.addOverlay(new GMarker(point));
}
// Call the geocoder with a 100ms delay
index++;
if (locations.length > index) {
setTimeout(geocoderFunction, 100);
}
});
}
map.setCenter(new GLatLng(38.00, -100.00), 3);
// Launch the geocoding process
geocoderFunction();
}
</script>
</body>
</html>
Using the V3 API:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps API Geocoding Demo</title>
<script src="http://maps.google.com/maps/api/js?sensor=false"
type="text/javascript"></script>
</head>
<body>
<div id="map_canvas" style="width: 400px; height: 300px"></div>
<script type="text/javascript">
// Prepare this list from ColdFusion
var locations = [
'New York, NY',
'Los Angeles, CA',
'Chicago, IL',
'Houston, TX',
'Phoenix, AZ'
];
var mapOpt = {
mapTypeId: google.maps.MapTypeId.TERRAIN,
center: new google.maps.LatLng(38.00, -100.00),
zoom: 3
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOpt);
var geocoder = new google.maps.Geocoder();
var index = 0;
var geocoderFunction = function () {
geocoder.geocode({ 'address': locations[index] }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
}
// Call the geocoder with a 100ms delay
index++;
if (locations.length > index) {
setTimeout(geocoderFunction, 100);
}
});
}
// Launch the geocoding process
geocoderFunction();
</script>
</body>
</html>
All you need to do is to render the JavaScript array locations from ColdFusion, instead of using the hardcoded one in the example.
Screenshot from the above example:
You need to actually add the marker to the map using the addOverlay method:
var point = new GLatLng(...);
map.addOverlay(new GMarker(point));
You can also add instances of the Marker class to your map:
map.addOverlay(marker);
See the Map Overlays docs:
http://code.google.com/apis/maps/documentation/javascript/v2/overlays.html

Categories

Resources