google directions: how to get transit_details? - google-maps

EDIT: this problem is solved thanks to the help of geocodezip who pointed me the right way in the comments...
problem:
i want transit-directions from google as plain text and i need the transit_details. i tried adding all variations of stuff like (which does not work):
steps[i].transit.arrival_stop.name
solution: most transit routes have the first and last steps walking. in this case, .transit does not exist and produces the error.
i fixed the code below accordingly (which now works).
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title></title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?"></script>
</head>
<body style="font-family: Arial; font-size: 12px; color:#FFFFFF;" bgcolor="#202020">
<div id="panel" style="width: 300px; float: left;"></div>
<div id="map" style="width: 300px; height: 300px;"></div>
<script type="text/javascript">
calcRoute();
function calcRoute() {
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
directionsDisplay.setMap(map);
var request = {
origin: 'Potsdamer Platz, 10785 Berlin',
destination: 'Falckensteinstraße, Berlin',
travelMode: google.maps.DirectionsTravelMode.TRANSIT,
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
writeDirectionsSteps(directionsDisplay.directions.routes[0].legs[0].steps);
}
else {
console.error('DirectionsStatus is ' + status);
}
});
}
function writeDirectionsSteps(steps) {
var directions = document.getElementById('panel');
directions.innerHTML = '';
for (var i = 0; i < steps.length; i++) {
directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
if (typeof steps[i].transit !== "undefined") {
directions.innerHTML += '<br/>' + steps[i].transit.arrival_stop.name;
}
}
}
</script>
</body>
</html>
(code based on: Google Maps Api v3: How to change the Default waypoint markers in the Directions (set)Panel?)
any help is appreciated a lot!

You need to code defensively. The .transit property will not be there in all the steps, only those that involve the actual transit itself (i.e. not on the walk to and from the station).
function writeDirectionsSteps(steps) {
var directions = document.getElementById('panel');
directions.innerHTML = '';
for (var i = 0; i < steps.length; i++) {
directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
// if .transit property exists
if (!!steps[i].transit) {
directions.innerHTML += '<br/>' + steps[i].transit.arrival_stop.name;
}
}
}
proof of concept fiddle
code snippet:
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var routeBounds = false;
var overlayWidth = 200; // Width of the overlay DIV
var leftMargin = 30; // Grace margin to avoid too close fits on the edge of the overlay
var rightMargin = 80; // Grace margin to avoid too close fits on the right and leave space for the controls
overlayWidth += leftMargin;
var start = new google.maps.LatLng(3.148173, 101.7148792);
var end = new google.maps.LatLng(3.1347725, 101.6893408);
function initialize() {
var btn1 = document.getElementById('calcRoute');
btn1.addEventListener('click', calcRoute);
var btn2 = document.getElementById('offsetMap');
btn2.addEventListener('click', offsetMap);
var btn3 = document.getElementById('fitAndOffsetMap');
btn3.addEventListener('click', fitAndOffsetMap);
var btn4 = document.getElementById('fitMap');
btn4.addEventListener('click', fitMap);
directionsDisplay = new google.maps.DirectionsRenderer({
draggable: true
});
var mapOptions = {
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: start,
panControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
},
zoomControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
}
};
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
directionsDisplay.setMap(map);
}
function offsetMap() {
if (routeBounds !== false) {
// Clear listener defined in directions results
google.maps.event.clearListeners(map, 'idle');
// Top right corner
var topRightCorner = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getNorthEast().lng());
// Top right point
var topRightPoint = fromLatLngToPoint(topRightCorner).x;
// Get pixel position of leftmost and rightmost points
var leftCoords = routeBounds.getSouthWest();
var leftMost = fromLatLngToPoint(leftCoords).x;
var rightMost = fromLatLngToPoint(routeBounds.getNorthEast()).x;
// Calculate left and right offsets
var leftOffset = (overlayWidth - leftMost);
var rightOffset = ((topRightPoint - rightMargin) - rightMost);
// Only if left offset is needed
if (leftOffset >= 0) {
if (leftOffset < rightOffset) {
var mapOffset = Math.round((rightOffset - leftOffset) / 2);
// Pan the map by the offset calculated on the x axis
map.panBy(-mapOffset, 0);
// Get the new left point after pan
var newLeftPoint = fromLatLngToPoint(leftCoords).x;
if (newLeftPoint <= overlayWidth) {
// Leftmost point is still under the overlay
// Offset map again
offsetMap();
}
} else {
// Cannot offset map at this zoom level otherwise both leftmost and rightmost points will not fit
// Zoom out and offset map again
map.setZoom(map.getZoom() - 1);
offsetMap();
}
}
}
}
function fromLatLngToPoint(latLng) {
var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getSouthWest().lng());
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(latLng);
return new google.maps.Point(Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale), Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale));
}
function calcRoute() {
var request = {
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode.TRANSIT,
transitOptions: {
departureTime: new Date("01/03/2017 9:00 AM EST")
}
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
// Define route bounds for use in offsetMap function
routeBounds = response.routes[0].bounds;
// Write directions steps
writeDirectionsSteps(response.routes[0].legs[0].steps);
// Wait for map to be idle before calling offsetMap function
google.maps.event.addListener(map, 'idle', function() {
// Offset map
offsetMap();
});
// Listen for directions changes to update bounds and reapply offset
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
// Get the updated route directions response
var updatedResponse = directionsDisplay.getDirections();
// Update route bounds
routeBounds = updatedResponse.routes[0].bounds;
// Fit updated bounds
map.fitBounds(routeBounds);
// Write directions steps
writeDirectionsSteps(updatedResponse.routes[0].legs[0].steps);
// Offset map
offsetMap();
});
}
});
}
function writeDirectionsSteps(steps) {
var directions = document.getElementById('overlayContent');
directions.innerHTML = '';
for (var i = 0; i < steps.length; i++) {
directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
// if .transit property exists
if (!!steps[i].transit) {
directions.innerHTML += '<br/>station name:' + steps[i].transit.arrival_stop.name;
}
}
}
function fitMap() {
if (routeBounds !== false) {
map.fitBounds(routeBounds);
}
}
function fitAndOffsetMap() {
if (routeBounds !== false) {
map.fitBounds(routeBounds);
offsetMap();
}
}
initialize();
body {
margin: 0;
padding: 0;
font-family: Arial;
}
#map-canvas {
height: 450px;
}
#overlay {
position: absolute;
width: 200px;
height: 450px;
background: black;
opacity: .8;
top: 0;
left: 0;
overflow: auto;
}
#overlayContent {
color: white;
padding: 10px 20px;
}
#overlayContent p {
font-size: 12px;
margin: 6px 0;
}
#overlayContent small {
display: block;
text-align: right;
font-style: italic;
}
small {
font-size: 9px;
}
i {
color: lightblue;
}
h1 {
font-size: 20px;
}
h5 {
font-size: 12px;
}
button {
margin: 20px 0 0 20px;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map-canvas"></div>
<div id="overlay">
<div id="overlayContent">
<h1>DIV OVERLAY</h1>
<h5>Routes should not be drawn below this element.</h5>
<h5>Click the <i>Calc route</i> button to draw the directions route.</h5>
<h5><i>Map offset</i> will be applied automatically.</h5>
<h5><i>Drag the route</i> to see how it is applied.</h5>
<h5>Click the <i>Offset map</i> button to reapply the offset.</h5>
<h5>Click the <i>Fit only</i> button to only fit route bounds.</h5>
<h5>Click the <i>Fit and offset map</i> button to fit to route bounds and reapply offset.</h5>
</div>
</div>
<button id="calcRoute">Calc route</button>
<button id="offsetMap">Offset map</button>
<button id="fitMap">Fit only</button>
<button id="fitAndOffsetMap">Fit and offset map</button>

Related

Google maps Snap to road demo not working | Google Maps API error: MissingKeyMapError

I am trying to get the Snap to Road demo working that is supplied here but I keep getting the error: Google Maps API error: MissingKeyMapError. I already searched around and this is the error Google gives you for either supplying no key or a invalid key but even if I generate a brand new key it won't work. It just gives me a blank screen.
Why is it throwing this error even though I supply the code with the API key?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Roads API Demo</title>
<style>
html,
body,
#map {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
#bar {
width: 240px;
background-color: rgba(255, 255, 255, 0.75);
margin: 8px;
padding: 4px;
border-radius: 4px;
}
#autoc {
width: 100%;
box-sizing: border-box;
}
</style>
<script src="jquery-3.2.1.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing,places"></script>
<script>
var apiKey = 'AIzaSyB3kpx3fgR9VT3WL2tp49QrbnyDdgygGeo';
var map;
var drawingManager;
var placeIdArray = [];
var polylines = [];
var snappedCoordinates = [];
function initialize() {
var mapOptions = {
zoom: 17,
center: {
lat: -33.8667,
lng: 151.1955
}
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
// Adds a Places search box. Searching for a place will center the map on that
// location.
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(
document.getElementById('bar'));
var autocomplete = new google.maps.places.Autocomplete(
document.getElementById('autoc'));
autocomplete.bindTo('bounds', map);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
});
// Enables the polyline drawing control. Click on the map to start drawing a
// polyline. Each click will add a new vertice. Double-click to stop drawing.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYLINE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYLINE
]
},
polylineOptions: {
strokeColor: '#696969',
strokeWeight: 2
}
});
drawingManager.setMap(map);
// Snap-to-road when the polyline is completed.
drawingManager.addListener('polylinecomplete', function(poly) {
var path = poly.getPath();
polylines.push(poly);
placeIdArray = [];
runSnapToRoad(path);
});
// Clear button. Click to remove all polylines.
$('#clear').click(function(ev) {
for (var i = 0; i < polylines.length; ++i) {
polylines[i].setMap(null);
}
polylines = [];
ev.preventDefault();
return false;
});
}
// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path) {
var pathValues = [];
for (var i = 0; i < path.getLength(); i++) {
pathValues.push(path.getAt(i).toUrlValue());
}
$.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: pathValues.join('|')
}, function(data) {
processSnapToRoadResponse(data);
drawSnappedPolyline();
getAndDrawSpeedLimits();
});
}
// Store snapped polyline returned by the snap-to-road service.
function processSnapToRoadResponse(data) {
snappedCoordinates = [];
placeIdArray = [];
for (var i = 0; i < data.snappedPoints.length; i++) {
var latlng = new google.maps.LatLng(
data.snappedPoints[i].location.latitude,
data.snappedPoints[i].location.longitude);
snappedCoordinates.push(latlng);
placeIdArray.push(data.snappedPoints[i].placeId);
}
}
// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline() {
var snappedPolyline = new google.maps.Polyline({
path: snappedCoordinates,
strokeColor: 'black',
strokeWeight: 3
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
}
// Gets speed limits (for 100 segments at a time) and draws a polyline
// color-coded by speed limit. Must be called after processing snap-to-road
// response.
function getAndDrawSpeedLimits() {
for (var i = 0; i <= placeIdArray.length / 100; i++) {
// Ensure that no query exceeds the max 100 placeID limit.
var start = i * 100;
var end = Math.min((i + 1) * 100 - 1, placeIdArray.length);
drawSpeedLimits(start, end);
}
}
// Gets speed limits for a 100-segment path and draws a polyline color-coded by
// speed limit. Must be called after processing snap-to-road response.
function drawSpeedLimits(start, end) {
var placeIdQuery = '';
for (var i = start; i < end; i++) {
placeIdQuery += '&placeId=' + placeIdArray[i];
}
$.get('https://roads.googleapis.com/v1/speedLimits',
'key=' + apiKey + placeIdQuery,
function(speedData) {
processSpeedLimitResponse(speedData, start);
}
);
}
// Draw a polyline segment (up to 100 road segments) color-coded by speed limit.
function processSpeedLimitResponse(speedData, start) {
var end = start + speedData.speedLimits.length;
for (var i = 0; i < speedData.speedLimits.length - 1; i++) {
var speedLimit = speedData.speedLimits[i].speedLimit;
var color = getColorForSpeed(speedLimit);
// Take two points for a single-segment polyline.
var coords = snappedCoordinates.slice(start + i, start + i + 2);
var snappedPolyline = new google.maps.Polyline({
path: coords,
strokeColor: color,
strokeWeight: 6
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
}
}
function getColorForSpeed(speed_kph) {
if (speed_kph <= 40) {
return 'purple';
}
if (speed_kph <= 50) {
return 'blue';
}
if (speed_kph <= 60) {
return 'green';
}
if (speed_kph <= 80) {
return 'yellow';
}
if (speed_kph <= 100) {
return 'orange';
}
return 'red';
}
$(window).on('load', function() {
initialize
});
</script>
</head>
<body>
<div id="map"></div>
<div id="bar">
<p class="auto"><input type="text" id="autoc" /></p>
<p><a id="clear" href="#">Click here</a> to clear map.</p>
</div>
</body>
</html>
If you haven't got an API KEY:
The script element that loads the API is missing the required authentication parameter. If you are using the standard Maps JavaScript API, you must use a key parameter with a valid API key.
Step 1: Get a Key from this URL
https://developers.google.com/maps/documentation/javascript/get-api-key
Step 2: Include your script with the API KEY
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
type="text/javascript"></script>
Or replace
var apiKey = 'YOUR_API_KEY';
If you got an API KEY
Google maps Snap to Road demo
Full Code
html, body, #map {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
#bar {
width: 240px;
background-color: rgba(255, 255, 255, 0.75);
margin: 8px;
padding: 4px;
border-radius: 4px;
}
#autoc {
width: 100%;
box-sizing: border-box;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Roads API Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="/_static/js/jquery-bundle.js"></script>
<script
src="https://maps.googleapis.com/maps/api/js?libraries=drawing,places"></script>
<script>
var apiKey = 'AIzaSyB3kpx3fgR9VT3WL2tp49QrbnyDdgygGeo';
var map;
var drawingManager;
var placeIdArray = [];
var polylines = [];
var snappedCoordinates = [];
function initialize() {
var mapOptions = {
zoom: 17,
center: {lat: -33.8667, lng: 151.1955}
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
// Adds a Places search box. Searching for a place will center the map on that
// location.
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(
document.getElementById('bar'));
var autocomplete = new google.maps.places.Autocomplete(
document.getElementById('autoc'));
autocomplete.bindTo('bounds', map);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
});
// Enables the polyline drawing control. Click on the map to start drawing a
// polyline. Each click will add a new vertice. Double-click to stop drawing.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYLINE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYLINE
]
},
polylineOptions: {
strokeColor: '#696969',
strokeWeight: 2
}
});
drawingManager.setMap(map);
// Snap-to-road when the polyline is completed.
drawingManager.addListener('polylinecomplete', function(poly) {
var path = poly.getPath();
polylines.push(poly);
placeIdArray = [];
runSnapToRoad(path);
});
// Clear button. Click to remove all polylines.
$('#clear').click(function(ev) {
for (var i = 0; i < polylines.length; ++i) {
polylines[i].setMap(null);
}
polylines = [];
ev.preventDefault();
return false;
});
}
// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path) {
var pathValues = [];
for (var i = 0; i < path.getLength(); i++) {
pathValues.push(path.getAt(i).toUrlValue());
}
$.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: pathValues.join('|')
}, function(data) {
processSnapToRoadResponse(data);
drawSnappedPolyline();
getAndDrawSpeedLimits();
});
}
// Store snapped polyline returned by the snap-to-road service.
function processSnapToRoadResponse(data) {
snappedCoordinates = [];
placeIdArray = [];
for (var i = 0; i < data.snappedPoints.length; i++) {
var latlng = new google.maps.LatLng(
data.snappedPoints[i].location.latitude,
data.snappedPoints[i].location.longitude);
snappedCoordinates.push(latlng);
placeIdArray.push(data.snappedPoints[i].placeId);
}
}
// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline() {
var snappedPolyline = new google.maps.Polyline({
path: snappedCoordinates,
strokeColor: 'black',
strokeWeight: 3
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
}
// Gets speed limits (for 100 segments at a time) and draws a polyline
// color-coded by speed limit. Must be called after processing snap-to-road
// response.
function getAndDrawSpeedLimits() {
for (var i = 0; i <= placeIdArray.length / 100; i++) {
// Ensure that no query exceeds the max 100 placeID limit.
var start = i * 100;
var end = Math.min((i + 1) * 100 - 1, placeIdArray.length);
drawSpeedLimits(start, end);
}
}
// Gets speed limits for a 100-segment path and draws a polyline color-coded by
// speed limit. Must be called after processing snap-to-road response.
function drawSpeedLimits(start, end) {
var placeIdQuery = '';
for (var i = start; i < end; i++) {
placeIdQuery += '&placeId=' + placeIdArray[i];
}
$.get('https://roads.googleapis.com/v1/speedLimits',
'key=' + apiKey + placeIdQuery,
function(speedData) {
processSpeedLimitResponse(speedData, start);
}
);
}
// Draw a polyline segment (up to 100 road segments) color-coded by speed limit.
function processSpeedLimitResponse(speedData, start) {
var end = start + speedData.speedLimits.length;
for (var i = 0; i < speedData.speedLimits.length - 1; i++) {
var speedLimit = speedData.speedLimits[i].speedLimit;
var color = getColorForSpeed(speedLimit);
// Take two points for a single-segment polyline.
var coords = snappedCoordinates.slice(start + i, start + i + 2);
var snappedPolyline = new google.maps.Polyline({
path: coords,
strokeColor: color,
strokeWeight: 6
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
}
}
function getColorForSpeed(speed_kph) {
if (speed_kph <= 40) {
return 'purple';
}
if (speed_kph <= 50) {
return 'blue';
}
if (speed_kph <= 60) {
return 'green';
}
if (speed_kph <= 80) {
return 'yellow';
}
if (speed_kph <= 100) {
return 'orange';
}
return 'red';
}
$(window).load(initialize);
</script>
</head>
<body>
<div id="map"></div>
<div id="bar">
<p class="auto"><input type="text" id="autoc"/></p>
<p><a id="clear" href="#">Click here</a> to clear map.</p>
</div>
</body>
</html>

google map javascript api transit

My requirement is, need to show all Transit Bus stations of a particular location(like state, city) and should able to mark only transit bus stations and show the infoWindow of that Transit Bus station using google map javascript api.
below is my html code, javascript marker logic also marks all the locations on the map i need to mark only transit bus stations
<!DOCTYPE html>
<html>
<head>
<title>Add/Remove Markers</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 50%;
width:50%;
position:inherit !important;
margin-top:50px !important;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
#map > div{
height:70% !important;
width:70% !important;
margin-top:50px !important;
}
a[href^="https://maps.google.com/maps"]{
display: none !important;
}
.gmnoprint a, .gmnoprint span, .gm-style-cc div {
display: none !important;
}
.gmnoprint div {
background: none !important;
}
</style>
</head>
<body>
<div id="floating-panel">
<input onclick="clearMarkers();" type=button value="Hide Markers">
<input onclick="showMarkers();" type=button value="Show All Markers">
<input onclick="deleteMarkers();" type=button value="Delete Markers">
</div>
<div id="map"></div>
<p>Click on the map to add markers.</p>
<script>
// In the following example, markers appear when the user clicks on the map.
// The markers are stored in an array.
// The user can then click an option to hide, show or delete the markers.
var map;
var markers = [];
function initMap() {
var haightAshbury = {lat: 37.769, lng: -122.446};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: haightAshbury,
disableDefaultUI: true
});
// This event listener will call addMarker() when the map is clicked.
map.addListener('click', function (event) {
addMarker(event.latLng);
});
// Adds a marker at the center of the map.
addMarker(haightAshbury);
}
// Adds a marker to the map and push to the array.
function addMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map
});
markers.push(marker);
//This code is to remove the marker from the map and the array
marker.addListener('click', function (e) {
var latIndex = markers.findIndex(x=>x.position.lat() == e.latLng.lat());
var lngIndex = markers.findIndex(x=>x.position.lng() == e.latLng.lng());
if ((latIndex != -1 && lngIndex != -1) && (latIndex == lngIndex)) {
markers[latIndex].setMap(null); // To remove the marker from the Map
markers.splice(latIndex, 1); // to remove the marker from the list of array
}
});
marker.addListener('mouseover', function (e) {
infowindow.open(map, this);
});
// assuming you also want to hide the infowindow when user mouses-out
marker.addListener('mouseout', function (e) {
infowindow.close();
});
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
}
// Shows any markers currently in the array.
function showMarkers() {
setMapOnAll(map);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
clearMarkers();
markers = [];
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=initMap">
</script>
</body>
</html>
var map;
var infowindow;
var service;
var markers = [];
var availableMarkers = [];
var unAvailableMarkers = [];
var selectedMarkers = [];
var globalResults = [];
function initialize(lat,lng)
{
var origin = new google.maps.LatLng(lat,lng);
map = new google.maps.Map(document.getElementById('map'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: origin,
zoom: 15,
disableDefaultUI: true
});
var request = {
location: origin,
radius: 2500,
types: ['bus_station']
};
infowindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
service.search(request, callback);
map.addListener('click', function (event) {
initialize(event.latLng.lat(), event.latLng.lng())
});
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
globalResults = results;
for (var i = 0; i < results.length; i++) {
if (i < 11)
createMarker(results[i], 'green');
else
createMarker(results[i], 'red');
}
}
}
function createMarker(place,color) {
var placeLoc = place.geometry.location;
var icon;
if (color == 'green')
icon = 'http://maps.google.com/mapfiles/ms/icons/green-dot.png';
else if (color == 'red')
icon = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png';
else
icon = 'http://maps.google.com/mapfiles/ms/icons/yellow-dot.png';
resizeIcon = icon;
var marker = null;
if (color == 'green') {
marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: resizeIcon
});
availableMarkers.push(marker);
}
else if (color == 'red') {
marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: resizeIcon
});
unAvailableMarkers.push(marker);
}
else {
marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: resizeIcon
});
selectedMarkers.push(marker);
}
markers.push(marker);
var content = '<div><strong>' + place.name + '</strong><br>' +
'Place ID: ' + place.place_id;
var more_content = '<img src="../Content/Images/1475150806_map-marker.png"/>'; // this is to show the image r any additional content
//make a request for further details
service.getDetails({ reference: place.reference }, function (place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
more_content = '<hr/><strong>Details';
if (place.website) {
more_content += '<br/><br/><strong>' + place.website + '';
}
}
});
google.maps.event.addListener(marker, 'mouseover', function () {
//infowindow.setContent(content + more_content);
infowindow.setContent(content);
infowindow.open(map, this);
});
// assuming you also want to hide the infowindow when user mouses-out
//google.maps.event.addListener(marker, 'mouseout', function (e) {
// infowindow.close();
//});
google.maps.event.addListener(marker, 'click', function (e) {
var latIndex = markers.findIndex(x=>x.position.lat() == e.latLng.lat());
var lngIndex = markers.findIndex(x=>x.position.lng() == e.latLng.lng());
var isAvailLat = availableMarkers.findIndex(x=>x.position.lat() == e.latLng.lat());
var isAvailLng = availableMarkers.findIndex(x=>x.position.lng() == e.latLng.lng());
var isUnAvailLat = unAvailableMarkers.findIndex(x=>x.position.lat() == e.latLng.lat());
var isUnAvailLng = unAvailableMarkers.findIndex(x=>x.position.lng() == e.latLng.lng());
var isSelectedLat = selectedMarkers.findIndex(x=>x.position.lat() == e.latLng.lat());
var isSelectedLng = selectedMarkers.findIndex(x=>x.position.lng() == e.latLng.lng());
if ((latIndex != -1 && lngIndex != -1) && (latIndex == lngIndex)) {
if ((isSelectedLat != -1 && isSelectedLng != -1) && (isSelectedLat == isSelectedLng)) {
selectedMarkers.splice(isSelectedLat, 1);
availableMarkers.push(markers[latIndex]);
marker.setIcon('http://maps.google.com/mapfiles/ms/icons/green-dot.png');
}
else if ((isAvailLat != -1 && isAvailLng != -1) && (isAvailLat == isAvailLng)) {
availableMarkers.splice(isAvailLat, 1);
selectedMarkers.push(markers[latIndex]);
marker.setIcon('http://maps.google.com/mapfiles/ms/icons/yellow-dot.png');
}
else if ((isUnAvailLat != -1 && isUnAvailLng != -1) && (isUnAvailLat == isUnAvailLng)) {
alert('This Transit is not avaliable, pls select a valid transit');
}
}
});
}
google.maps.event.addDomListener(window, 'load', function () { initialize(39.759444, -84.191667); });
/*These styles area added to hide the google footer*/
a[href^="http://maps.google.com/maps"] {
display: none !important;
}
a[href^="https://maps.google.com/maps"] {
display: none !important;
}
.gmnoprint a, .gmnoprint span, .gm-style-cc {
display: none;
}
.gmnoprint div {
background: none !important;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Transit</title>
</head>
<body>
<div id="map" style="height:600px;"></div>
<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places"></script>
</body>
</html>

Google Direction API directionsService.route() does not return result

I have tried to utilise the direction api to calculate distance between two places. However, the .route() service does not seem to hold.
$scope.getRes = function(id) {
$scope.bookingReference = {};
$http.get('/api/carpooler/'+id)
.success(function(data) {
data.travelDate = new moment(data.travelDate).format("MMM Do YYYY");
data.travelTime = new moment(data.travelTime).format("h:mm:ss a");
$scope.bookingReference = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
for(i = 0;i<$scope.bookings.length;i++) {
dd = calcRoute($scope.bookings[i].Destination,$scope.bookingReference.Destination);
if( dd < 5000) {// 5 KM
$scope.bookingResultArray.push($scope.bookings[i]);
}
}
$scope.status2 = true;
};
I am calling the calcRoute to return the distance.
var directionsService = new google.maps.DirectionsService();
function calcRoute(ref1,ref2) {
var start = String(ref1);
var end = String(ref2);
var args = {
origin:start,
destination:end,
travelMode: google.maps.TravelMode.DRIVING
}
directionsService.route(args, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var myroute=directionsDisplay.directions.routes[0];
} else {
alert("fail");
}
});
var distance= 0;
for(i = 0; i < myroute.legs.length; i++){
distance += myroute.legs[i].distance.value;
//for each 'leg'(route between two waypoints) we get the distance and add it to the total
}
return distance;
};
I get the following error :
Error: myroute is not defined
calcRoute#http://localhost:3000/controllers/home.js:73:12
$scope.getRes#http://localhost:3000/controllers/home.js:91:20
Parser.prototype.functionCall/<#http://localhost:3000/vendor/angular.js:11026:15
ngEventHandler/</<#http://localhost:3000/vendor/angular.js:20468:17
$RootScopeProvider/this.$get</Scope.prototype.$eval#http://localhost:3000/vendor/angular.js:12874:16
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://localhost:3000/vendor/angular.js:12972:18
ngEventHandler/<#http://localhost:3000/vendor/angular.js:20467:15
m.event.dispatch#https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:8497
m.event.add/r.handle#https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js:4:5235
The source for google maps api
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="http://maps.googleapis.com/maps/api/js?libraries=places"></script>
I cannot figure out why the status is always not okay in the directionsService.route call [the alert with "fail" is always the one to turn up]
Am i doing it wrong? I am using angular but i think its not the issue.
You can't access myroute until it exists (inside the DirectionsService callback function). There you need to use the value:
function calcRoute(ref1, ref2) {
var start = String(ref1);
var end = String(ref2);
var args = {
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING
}
directionsService.route(args, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var myroute = directionsDisplay.directions.routes[0];
var distance = 0;
for (i = 0; i < myroute.legs.length; i++) {
distance += myroute.legs[i].distance.value;
//for each 'leg'(route between two waypoints) we get the distance and add it to the total
}
document.getElementById('distance').innerHTML = distance +" meters";
} else {
alert("fail");
}
});
};
proof of concept fiddle
code snippet:
var geocoder;
var map;
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
function initialize() {
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var directionsService = new google.maps.DirectionsService();
directionsDisplay.setMap(map);
calcRoute("New York, NY", "Baltimore, MD");
}
google.maps.event.addDomListener(window, "load", initialize);
function calcRoute(ref1, ref2) {
var start = String(ref1);
var end = String(ref2);
var args = {
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING
}
directionsService.route(args, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var myroute = directionsDisplay.directions.routes[0];
var distance = 0;
for (i = 0; i < myroute.legs.length; i++) {
distance += myroute.legs[i].distance.value;
//for each 'leg'(route between two waypoints) we get the distance and add it to the total
}
document.getElementById('distance').innerHTML = distance + " meters";
} else {
alert("fail");
}
});
};
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="distance"></div>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>

How to select a polygon covered by another polygon

when I draw the last two polygons has a z-index greater than the first, so "hidden" at first and I can not choose, then what I'm trying to do is change the z-index by area
I try this
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
lastPolygon = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function() {
setSelection(newShape);
});
setSelection(newShape);
}
console.log(newShape);
ArrayDeZonas.push(newShape);
zIndex += 1
ordenarZonasDescendente(ArrayDeZonas);
});
function ordenarZonasDescendente(zonas) {
var zonaAuxiliar;
for (var i = 0; i < getCantidadElementos(zonas); i++) {
for (var j = i+1; j < getCantidadElementos(zonas); j++) {
var area1 = getArea(GetGLatLngArray(zonas[i]));
var area2 = getArea(GetGLatLngArray(zonas[j]));
if (area1 < area2) {
zonas[i].zIndex = zIndex //Smaller area greater z Index
zonas[j].zIndex = zIndex-1; //Larger area less zIndexx
}
}
}
return zonas;
}
in console output
in consola.log () it shows me that their z-index changed and are fine, but not updated on the map, I'm not able to select the polygon that is inside.
Sorry for my English, I hope it is understood what I want, thank you very much!
I would suggest:
use the geometry library to compute the area
var area = google.maps.geometry.spherical.computeArea(zonas[i].getPath());
use the javascript array sort to order the polygons
zonas.sort(byArea);
function byArea(a, b) {
if (a._area < b._area) {
return -1;
}
if (a._area > b._area) {
return 1;
}
// a must be equal to b
return 0;
}
Then you can do this:
function ordenarZonasDescendente(zonas) {
for (var i = 0; i < zonas.length; i++) {
var area = google.maps.geometry.spherical.computeArea(zonas[i].getPath());
zonas[i]._area = area;
}
zonas.sort(byArea);
for (var i = 0; i < zonas.length; i++) {
zonas[i].set("zIndex", (zonas.length - i));
}
return zonas;
}
proof of concept fiddle
code snippet:
$(document).ready(function() {
function ordenarZonasDescendente(zonas) {
for (var i = 0; i < zonas.length; i++) {
var area = google.maps.geometry.spherical.computeArea(zonas[i].getPath());
zonas[i]._area = area;
}
zonas.sort(byArea);
for (var i = 0; i < zonas.length; i++) {
zonas[i].set("zIndex", (zonas.length - i));
}
return zonas;
}
function byArea(a, b) {
if (a._area < b._area) {
return -1;
}
if (a._area > b._area) {
return 1;
}
// a must be equal to b
return 0;
}
var ArrayDeZonas = [];
var zIndex = 0;
var infowindow = new google.maps.InfoWindow();
var mapHeight = '400px';
// $('#map-canvas').css('height', mapHeight);
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {
lat: 47.53187912201915,
lng: 7.705222390807307
},
zoom: 20,
});
var map_drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: null,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT,
drawingModes: [
google.maps.drawing.OverlayType.MARKER,
google.maps.drawing.OverlayType.POLYGON
]
},
//drawingMode: google.maps.drawing.OverlayType.POLYGON,
markerOptions: {
draggable: true
},
polylineOptions: {
editable: true,
draggable: true
},
map: map
});
google.maps.event.addListener(map_drawingManager, 'overlaycomplete', function(e) {
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
map_drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
lastPolygon = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function(evt) {
newShape.setOptions({
draggable: true
});
infowindow.setContent("vertices: " + this.getPath().getLength() + "<br>" + "area: " + google.maps.geometry.spherical.computeArea(this.getPath()) + "<br>" + "zIndex: " + this.get("zIndex") + "<br>" + "coords: " + evt.latLng.toUrlValue(6));
infowindow.setPosition(evt.latLng);
infowindow.open(map);
/*
setSelection(newShape);
*/
});
/*
setSelection(newShape);
*/
console.log(newShape);
ArrayDeZonas.push(newShape);
zIndex += 1;
ordenarZonasDescendente(ArrayDeZonas);
}
});
})
html,
body,
#map-canvas {
height: 500px;
width: 750px;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,drawing"></script>
<div id="map-canvas" style="border: 2px solid #3872ac;"></div>

Google Maps JavaScript API v3 Distance Matrix send lat and lng but return address

every one.
you can see this link.
Google.
this link show parameter variable origin1 and variable destinationB is mean lat and lng.
but i click calculate distances return there address.
i want lat and lng result.
how can?
i need help.
thank you friends.
The response of the DistanceMatrixService doesn't contain LatLng's.
When you take a look at the code you'll see that the LatLng's(used to draw the markers) will be requested via geocoding.
Of course you would be able to use the hardcoded LatLng's, but the result may differ, because the locations returned by the DistanceMatrixService must not be equal to these values.
How to get LatLng's regardless of the input-type(address or LatLng)?
The geocoding runs asynchronously, there is no guarantee that the results will return in a specific order. Therefore it's not possible to create a string like the demo does.
Instead create DOMNodes(where you want to display the LatLng's), pass these nodes as argument to addMarker , and in the geocode-callback set the content of the node to the desired value
var map;
var geocoder;
var bounds = new google.maps.LatLngBounds();
var markersArray = [];
var origin1 = new google.maps.LatLng(55.930, -3.118);
var origin2 = 'Greenwich, England';
var destinationA = 'Stockholm, Sweden';
var destinationB = new google.maps.LatLng(50.087, 14.421);
var destinationIcon = 'http://www.google.com/mapfiles/dd-end.png';
var originIcon = 'http://www.google.com/mapfiles/dd-start.png';
function initialize() {
var opts = {
center: new google.maps.LatLng(55.53, 9.4),
zoom: 10
};
map = new google.maps.Map(document.getElementById('map-canvas'), opts);
geocoder = new google.maps.Geocoder();
}
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin1, origin2],
destinations: [destinationA, destinationB],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('outputDiv');
outputDiv.innerHTML = '';
deleteOverlays();
for (var i = 0; i < origins.length; i++) {
//create a new "row"
var row=outputDiv.appendChild(document.createElement('div'));
var results = response.rows[i].elements;
//origin-marker
addMarker(origins[i], false,row.appendChild(document.createElement('code')));
//a list for the destinations
var list=row.appendChild(document.createElement('ul'));
for (var j = 0; j < results.length; j++) {
var item=list.appendChild(document.createElement('li'));
item.appendChild(document.createTextNode(' to '));
//destination-marker
addMarker(destinations[j], true,item.appendChild(document.createElement('code')));
item.appendChild(document.createTextNode([': ',
results[j].distance.text,
' in ',
results[j].duration.text
].join('')));
}
}
}
}
function addMarker(location, isDestination,node) {
var icon;
if (isDestination) {
icon = destinationIcon;
} else {
icon = originIcon;
}
geocoder.geocode({'address': location}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
bounds.extend(results[0].geometry.location);
map.fitBounds(bounds);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
icon: icon
});
markersArray.push(marker);
node.appendChild(document.createTextNode('('+marker.getPosition().toUrlValue()+')'));
node.setAttribute('title',location);
node.style.background=(isDestination)?'red':'green';
google.maps.event.addDomListener(node,'click',function(){map.panTo(marker.getPosition())})
} else {
alert('Geocode was not successful for the following reason: '
+ status);
}
});
}
function deleteOverlays() {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
markersArray = [];
}
google.maps.event.addDomListener(window, 'load', initialize);
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
width: 50%;
}
#content-pane {
float:right;
width:48%;
padding-left: 2%;
}
#outputDiv>div:nth-child(n+2){
border-top:1px dotted silver;
}
#outputDiv code{
cursor:pointer;
color:#fff;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3&.js"></script>
<div id="content-pane">
<button type="button" onclick="calculateDistances();">
Calculate distances
</button>
<div id="outputDiv"></div>
</div>
<div id="map-canvas"></div>