Places UI Kit: A ready-to-use library that provides room for customization and low-code development. Try it out, and share your input on your UI Kit experience.

Route demo

European Economic Area (EEA) developers

The Route demo lets you specify an origin and destination as a latitude/longitude coordinates pair or as a place ID. To copy the latitude/longitude coordinates, find and click a location on the map, and then paste the location into the form.

After you select Get route, the demo displays the response from the computeRoutes method as a route on the map.

[フレーム]

See the complete example source code

The following demo lets you experiment with creating lots of different kinds of routes. Click the map to copy the latitude/longitude coordinates of a location. Paste the coordinates into the form to get directions.

TypeScript

letmarkers:google.maps.marker.AdvancedMarkerElement[]=[];
letpolylines:google.maps.Polyline[]=[];
letwaypointInfoWindow:google.maps.InfoWindow|null=null;
interfacePlaceAutocompleteSelection{
predictionText:string|null;
location:google.maps.LatLng|null;
}
constoriginAutocompleteSelection:PlaceAutocompleteSelection={
predictionText:null,
location:null,
};
constdestinationAutocompleteSelection:PlaceAutocompleteSelection={
predictionText:null,
location:null,
};
asyncfunctioninit(){
const[
{InfoWindow},
{AdvancedMarkerElement},
//prettier-ignore
//@ts-ignore
{PlaceAutocompleteElement},
//prettier-ignore
//@ts-ignore
{ComputeRoutesExtraComputation,ReferenceRoute,Route,RouteLabel},
]=awaitPromise.all([
google.maps.importLibrary('maps')asPromise<google.maps.MapsLibrary>,
google.maps.importLibrary(
'marker'
)asPromise<google.maps.MarkerLibrary>,
google.maps.importLibrary(
'places'
)asPromise<google.maps.PlacesLibrary>,
google.maps.importLibrary(
'routes'
)asPromise<google.maps.RoutesLibrary>,
]);
constmap=document.getElementById('map')asgoogle.maps.MapElement;
attachSubmitListener();
initializeLocationInputs();
attachMapClickListener();
attachTravelModeListener();
attachAlertWindowListener();
attachDepartureTimeListener();
functionattachSubmitListener(){
constcomputeRoutesForm=document.getElementById(
'compute-routes-form'
)asHTMLFormElement;
computeRoutesForm.addEventListener('submit',(event)=>{
event.preventDefault();
sendRequest(newFormData(computeRoutesForm));
});
}
asyncfunctionsendRequest(formData:FormData){
clearMap();
try{
const{routes}=awaitRoute.computeRoutes(
buildComputeRoutesJsRequest(formData)
);
if(!routes){
console.log('No routes returned.');
return;
}
console.log('Routes:');
routes.forEach((route)=>{
console.log(route.toJSON());
});
awaitPromise.all(
routes.map((route)=>
drawRoute(
route,
!!route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
)
)
);
}catch(error:unknown){
console.error(error);
setErrorMessage((errorasError).message||'Unknown error.');
}
}
functionbuildComputeRoutesJsRequest(
formData:FormData
//prettier-ignore
//@ts-ignore
):google.maps.routes.ComputeRoutesRequest{
consttravelMode=
(formData.get('travel_mode')asstring)===''
?undefined
:(formData.get('travel_mode')asgoogle.maps.TravelMode);
//prettier-ignore
//@ts-ignore
constextraComputations:google.maps.routes.ComputeRoutesExtraComputation[]=
[];
//prettier-ignore
//@ts-ignore
constrequestedReferenceRoutes:google.maps.routes.ReferenceRoute[]=[];
//prettier-ignore
//@ts-ignore
consttransitPreference:google.maps.routes.TransitPreference={};
constrequest={
origin:{
location:buildComputeRoutesLocation(
originAutocompleteSelection,
formData.get('origin_location'),
formData.get('heading_org'),
travelMode
),
vehicleStopover:formData.get('origin_stopover')==='on',
sideOfRoad:formData.get('origin_side_of_road')==='on',
},
destination:{
location:buildComputeRoutesLocation(
destinationAutocompleteSelection,
formData.get('destination_location'),
formData.get('heading_dest'),
travelMode
),
vehicleStopover:formData.get('destination_stopover')==='on',
sideOfRoad:formData.get('destination_side_of_road')==='on',
},
fields:Array.from(
document.querySelectorAll(
'ul#fields li input[type="checkbox"]:checked'
),
(input)=>(inputasHTMLInputElement).value
),
travelMode:travelModeasgoogle.maps.TravelMode,
routingPreference:
formData.get('routing_preference')===''
?undefined
:(formData.get(
'routing_preference'
//prettier-ignore
//@ts-ignore
)asgoogle.maps.routes.RoutingPreference),
polylineQuality:
formData.get('polyline_quality')===''
?undefined
:(formData.get(
'polyline_quality'
//prettier-ignore
//@ts-ignore
)asgoogle.maps.routes.PolylineQuality),
computeAlternativeRoutes:
formData.get('compute_alternative_routes')==='on',
routeModifiers:{
avoidTolls:formData.get('avoid_tolls')==='on',
avoidHighways:formData.get('avoid_highways')==='on',
avoidFerries:formData.get('avoid_ferries')==='on',
avoidIndoor:formData.get('avoid_indoor')==='on',
},
departureTime:
(formData.get('departure_time')asstring)===''
?undefined
:newDate(formData.get('departure_time')asstring),
extraComputations,
requestedReferenceRoutes,
transitPreference,
};
if(formData.get('traffic_aware_polyline')==='on'){
extraComputations.push(
ComputeRoutesExtraComputation.TRAFFIC_ON_POLYLINE
);
}
if(formData.get('shorter_distance')==='on'){
requestedReferenceRoutes.push(ReferenceRoute.SHORTER_DISTANCE);
}
if(formData.get('eco_routes')==='on'){
requestedReferenceRoutes.push(ReferenceRoute.FUEL_EFFICIENT);
extraComputations.push(
ComputeRoutesExtraComputation.FUEL_CONSUMPTION
);
//prettier-ignore
//@ts-ignore
(request.routeModifiersasgoogle.maps.routes.RouteModifiers).vehicleInfo=
{
emissionType:formData.get(
'emission_type'
//prettier-ignore
//@ts-ignore
)asgoogle.maps.routes.VehicleEmissionType,
};
}
if(travelMode===google.maps.TravelMode.TRANSIT){
constselectedTransitModes=document.querySelectorAll(
'ul#transitModes li input[type="checkbox"]:checked'
);
transitPreference.allowedTransitModes=Array.from(
selectedTransitModes,
(input)=>
(inputasHTMLInputElement).valueasgoogle.maps.TransitMode
);
transitPreference.routingPreference=
formData.get('transit_preference')===''
?undefined
:(formData.get(
'transit_preference'
)asgoogle.maps.TransitRoutePreference);
}
returnrequest;
}
functionbuildComputeRoutesLocation(
autocompleteSelection:PlaceAutocompleteSelection,
locationInput?:FormDataEntryValue|null,
headingInput?:FormDataEntryValue|null,
travelModeInput?:FormDataEntryValue|null
//prettier-ignore
//@ts-ignore
):string|google.maps.routes.DirectionalLocationLiteral{
if(!locationInput){
thrownewError('Location is required.');
}
constlatLngRegex=/^-?\d+(\.\d+)?,\s*-?\d+(\.\d+)?$/;
constlocation=locationInputasstring;
constheading=
headingInput && travelModeInput!=='TRANSIT'
?Number(headingInputasstring)
:undefined;
if(
autocompleteSelection.predictionText===location&&
autocompleteSelection.location
){
// Use the lat/lng from the autocomplete selection if the current input
// matches the autocomplete prediction text
return{
lat:autocompleteSelection.location.lat(),
lng:autocompleteSelection.location.lng(),
altitude:0,
heading,
};
}elseif(latLngRegex.test(location)){
// If the current input looks like a lat/lng, format it as a
// google.maps.routes.DirectionalLocationLiteral
return{
lat:Number(location.split(',')[0]),
lng:Number(location.split(',')[1]),
altitude:0,
heading,
};
}
// Otherwise return the input location string
returnlocation;
}
functionsetErrorMessage(error:string){
constalertBox=document.getElementById('alert')asHTMLDivElement;
alertBox.querySelector('p')!.textContent=error;
alertBox.style.display='flex';
}
asyncfunctiondrawRoute(
//prettier-ignore
//@ts-ignore
route:google.maps.routes.Route,
isPrimaryRoute:boolean
){
polylines=polylines.concat(
route.createPolylines({
polylineOptions:isPrimaryRoute
?{map:map.innerMap,zIndex:1}
:{
map:map.innerMap,
strokeColor:'#669DF6',
strokeOpacity:0.5,
strokeWeight:8,
},
colorScheme:map.innerMap.get('colorScheme'),
})
);
if(isPrimaryRoute){
markers=markers.concat(
awaitroute.createWaypointAdvancedMarkers({
map:map.innerMap,
zIndex:1,
})
);
if(route.viewport){
map.innerMap.fitBounds(route.viewport);
}
}
addRouteLabel(route,Math.floor(route.path!.length/2));
}
//prettier-ignore
//@ts-ignore
functionaddRouteLabel(route:google.maps.routes.Route,index:number){
constrouteTag=document.createElement('div');
routeTag.className='route-tag';
if(route.routeLabels && route.routeLabels.length > 0){
constp=document.createElement('p');
route.routeLabels.forEach((label,i)=>{
if(label.includes(RouteLabel.FUEL_EFFICIENT)){
routeTag.classList.add('eco');
}
if(label.includes(RouteLabel.DEFAULT_ROUTE_ALTERNATE)){
routeTag.classList.add('alternate');
}
if(label.includes(RouteLabel.SHORTER_DISTANCE)){
routeTag.classList.add('shorter-distance');
}
p.appendChild(document.createTextNode(label));
if(i < route.routeLabels!.length-1){
p.appendChild(document.createElement('br'));
}
});
routeTag.appendChild(p);
}
constdetailsDiv=document.createElement('div');
detailsDiv.className='details';
if(route.localizedValues){
constdistanceP=document.createElement('p');
distanceP.textContent=`Distance: ${route.localizedValues.distance!}`;
detailsDiv.appendChild(distanceP);
constdurationP=document.createElement('p');
durationP.textContent=`Duration: ${route.localizedValues.duration}`!;
detailsDiv.appendChild(durationP);
}
if(route.travelAdvisory?.fuelConsumptionMicroliters){
constfuelP=document.createElement('p');
fuelP.textContent=`Fuel consumption: ${(
route.travelAdvisory.fuelConsumptionMicroliters/1e6
).toFixed(2)} L`;
detailsDiv.appendChild(fuelP);
}
routeTag.appendChild(detailsDiv);
constmarker=newAdvancedMarkerElement({
map:map.innerMap,
position:route.path![index],
content:routeTag,
zIndex:route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
?1
:undefined,
});
markers.push(marker);
}
functionclearMap(){
markers.forEach((marker)=>{
marker.map=null;
});
markers.length=0;
polylines.forEach((polyline)=>{
polyline.setMap(null);
});
polylines.length=0;
}
functionattachMapClickListener(){
if(!map||!map.innerMap){
return;
}
letinfoWindowAlert=document.getElementById('infowindow-alert');
if(!infoWindowAlert){
infoWindowAlert=document.createElement('div');
infoWindowAlert.id=infoWindowAlert.className='infowindow-alert';
infoWindowAlert.textContent='Lat/Lng are copied to clipboard';
}
constinfoWindow=newInfoWindow();
letcloseWindowTimeout:number;
map.innerMap.addListener(
'click',
async(mapsMouseEvent:google.maps.MapMouseEvent)=>{
if(!mapsMouseEvent.latLng){
return;
}
infoWindow.close();
if(closeWindowTimeout){
clearTimeout(closeWindowTimeout);
}
infoWindow.setContent(infoWindowAlert);
infoWindow.setPosition({
lat:mapsMouseEvent.latLng.lat(),
lng:mapsMouseEvent.latLng.lng(),
});
awaitnavigator.clipboard.writeText(
`${mapsMouseEvent.latLng.lat()},${mapsMouseEvent.latLng.lng()}`
);
infoWindow.open(map.innerMap);
closeWindowTimeout=window.setTimeout(()=>{
infoWindow.close();
},2000);
}
);
}
functionattachTravelModeListener(){
consttravelMode=document.getElementById(
'travel-mode'
)asHTMLSelectElement;
constroutingPreference=document.getElementById(
'routing-preference'
)asHTMLSelectElement;
consttrafficAwarePolyline=document.getElementById(
'traffic-aware-polyline'
)asHTMLInputElement;
constecoRoutes=document.getElementById(
'eco-routes'
)asHTMLInputElement;
constemissionType=document.getElementById(
'emission-type'
)asHTMLSelectElement;
travelMode.addEventListener('change',()=>{
// Toggle the Routing Preference selection and Traffic Aware Polyline
// selection for WALKING, BICYCLING, and TRANSIT modes.
if(
travelMode.value==='WALKING'||
travelMode.value==='BICYCLING'||
travelMode.value==='TRANSIT'
){
routingPreference.disabled=true;
routingPreference.value='';
}else{
routingPreference.disabled=false;
routingPreference.value=
routingPreference.value||'TRAFFIC_UNAWARE';
}
toggleTrafficAwarePolyline();
// Toggle transit options for Transit mode
(
document.getElementById('transit-options')asHTMLElement
).style.display=travelMode.value==='TRANSIT'?'flex':'none';
});
routingPreference.addEventListener('change',()=>{
toggleTrafficAwarePolyline();
});
ecoRoutes.addEventListener('change',()=>{
if(ecoRoutes.checked){
emissionType.disabled=false;
}else{
emissionType.disabled=true;
}
});
functiontoggleTrafficAwarePolyline(){
if(
!routingPreference.value||
routingPreference.value==='TRAFFIC_UNAWARE'
){
trafficAwarePolyline.checked=false;
trafficAwarePolyline.disabled=true;
}else{
trafficAwarePolyline.disabled=false;
}
}
}
functionattachAlertWindowListener(){
constalertBox=document.getElementById('alert')asHTMLDivElement;
constcloseBtn=alertBox.querySelector('.close')asHTMLButtonElement;
closeBtn.addEventListener('click',()=>{
if(alertBox.style.display!=='none'){
alertBox.style.display='none';
}
});
}
functioninitializeLocationInputs(){
constoriginAutocomplete=newPlaceAutocompleteElement({
name:'origin_location',
});
constdestinationAutocomplete=newPlaceAutocompleteElement({
name:'destination_location',
});
[
[originAutocomplete,originAutocompleteSelection],
[destinationAutocomplete,destinationAutocompleteSelection],
].forEach(([autocomplete,autocompleteData])=>{
autocomplete.addEventListener(
'gmp-select',
//prettier-ignore
//@ts-ignore
async(event:google.maps.places.PlacePredictionSelectEvent)=>{
autocompleteData.predictionText=event.placePrediction.text.text;
constplace=event.placePrediction.toPlace();
awaitplace.fetchFields({
fields:['location'],
});
autocompleteData.location=place.location;
}
);
});
document
.getElementById('origin-input')
?.appendChild(originAutocomplete);
document
.getElementById('destination-input')
?.appendChild(destinationAutocomplete);
}
functionattachDepartureTimeListener(){
constdepartureTime=document.getElementById(
'departure-time'
)asHTMLInputElement;
constutcOutput=document.getElementById(
'utc-output'
)asHTMLParagraphElement;
departureTime.addEventListener('change',()=>{
utcOutput.textContent=`UTC time: ${newDate(
departureTime.value
).toUTCString()}`;
});
}
}
window.addEventListener('load',init);

JavaScript

letmarkers=[];
letpolylines=[];
letwaypointInfoWindow=null;
constoriginAutocompleteSelection={
predictionText:null,
location:null,
};
constdestinationAutocompleteSelection={
predictionText:null,
location:null,
};
asyncfunctioninit(){
const[{InfoWindow},{AdvancedMarkerElement},
//prettier-ignore
//@ts-ignore
{PlaceAutocompleteElement},
//prettier-ignore
//@ts-ignore
{ComputeRoutesExtraComputation,ReferenceRoute,Route,RouteLabel},]=awaitPromise.all([
google.maps.importLibrary('maps'),
google.maps.importLibrary('marker'),
google.maps.importLibrary('places'),
google.maps.importLibrary('routes'),
]);
constmap=document.getElementById('map');
attachSubmitListener();
initializeLocationInputs();
attachMapClickListener();
attachTravelModeListener();
attachAlertWindowListener();
attachDepartureTimeListener();
functionattachSubmitListener(){
constcomputeRoutesForm=document.getElementById('compute-routes-form');
computeRoutesForm.addEventListener('submit',(event)=>{
event.preventDefault();
sendRequest(newFormData(computeRoutesForm));
});
}
asyncfunctionsendRequest(formData){
clearMap();
try{
const{routes}=awaitRoute.computeRoutes(buildComputeRoutesJsRequest(formData));
if(!routes){
console.log('No routes returned.');
return;
}
console.log('Routes:');
routes.forEach((route)=>{
console.log(route.toJSON());
});
awaitPromise.all(routes.map((route)=>drawRoute(route,!!route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE))));
}
catch(error){
console.error(error);
setErrorMessage(error.message||'Unknown error.');
}
}
functionbuildComputeRoutesJsRequest(formData
//prettier-ignore
//@ts-ignore
){
consttravelMode=formData.get('travel_mode')===''
?undefined
:formData.get('travel_mode');
//prettier-ignore
//@ts-ignore
constextraComputations=[];
//prettier-ignore
//@ts-ignore
constrequestedReferenceRoutes=[];
//prettier-ignore
//@ts-ignore
consttransitPreference={};
constrequest={
origin:{
location:buildComputeRoutesLocation(originAutocompleteSelection,formData.get('origin_location'),formData.get('heading_org'),travelMode),
vehicleStopover:formData.get('origin_stopover')==='on',
sideOfRoad:formData.get('origin_side_of_road')==='on',
},
destination:{
location:buildComputeRoutesLocation(destinationAutocompleteSelection,formData.get('destination_location'),formData.get('heading_dest'),travelMode),
vehicleStopover:formData.get('destination_stopover')==='on',
sideOfRoad:formData.get('destination_side_of_road')==='on',
},
fields:Array.from(document.querySelectorAll('ul#fields li input[type="checkbox"]:checked'),(input)=>input.value),
travelMode:travelMode,
routingPreference:formData.get('routing_preference')===''
?undefined
:formData.get('routing_preference'
//prettier-ignore
//@ts-ignore
),
polylineQuality:formData.get('polyline_quality')===''
?undefined
:formData.get('polyline_quality'
//prettier-ignore
//@ts-ignore
),
computeAlternativeRoutes:formData.get('compute_alternative_routes')==='on',
routeModifiers:{
avoidTolls:formData.get('avoid_tolls')==='on',
avoidHighways:formData.get('avoid_highways')==='on',
avoidFerries:formData.get('avoid_ferries')==='on',
avoidIndoor:formData.get('avoid_indoor')==='on',
},
departureTime:formData.get('departure_time')===''
?undefined
:newDate(formData.get('departure_time')),
extraComputations,
requestedReferenceRoutes,
transitPreference,
};
if(formData.get('traffic_aware_polyline')==='on'){
extraComputations.push(ComputeRoutesExtraComputation.TRAFFIC_ON_POLYLINE);
}
if(formData.get('shorter_distance')==='on'){
requestedReferenceRoutes.push(ReferenceRoute.SHORTER_DISTANCE);
}
if(formData.get('eco_routes')==='on'){
requestedReferenceRoutes.push(ReferenceRoute.FUEL_EFFICIENT);
extraComputations.push(ComputeRoutesExtraComputation.FUEL_CONSUMPTION);
//prettier-ignore
//@ts-ignore
request.routeModifiers.vehicleInfo=
{
emissionType:formData.get('emission_type'
//prettier-ignore
//@ts-ignore
),
};
}
if(travelMode===google.maps.TravelMode.TRANSIT){
constselectedTransitModes=document.querySelectorAll('ul#transitModes li input[type="checkbox"]:checked');
transitPreference.allowedTransitModes=Array.from(selectedTransitModes,(input)=>input.value);
transitPreference.routingPreference=
formData.get('transit_preference')===''
?undefined
:formData.get('transit_preference');
}
returnrequest;
}
functionbuildComputeRoutesLocation(autocompleteSelection,locationInput,headingInput,travelModeInput
//prettier-ignore
//@ts-ignore
){
if(!locationInput){
thrownewError('Location is required.');
}
constlatLngRegex=/^-?\d+(\.\d+)?,\s*-?\d+(\.\d+)?$/;
constlocation=locationInput;
constheading=headingInput && travelModeInput!=='TRANSIT'
?Number(headingInput)
:undefined;
if(autocompleteSelection.predictionText===location&&
autocompleteSelection.location){
// Use the lat/lng from the autocomplete selection if the current input
// matches the autocomplete prediction text
return{
lat:autocompleteSelection.location.lat(),
lng:autocompleteSelection.location.lng(),
altitude:0,
heading,
};
}
elseif(latLngRegex.test(location)){
// If the current input looks like a lat/lng, format it as a
// google.maps.routes.DirectionalLocationLiteral
return{
lat:Number(location.split(',')[0]),
lng:Number(location.split(',')[1]),
altitude:0,
heading,
};
}
// Otherwise return the input location string
returnlocation;
}
functionsetErrorMessage(error){
constalertBox=document.getElementById('alert');
alertBox.querySelector('p').textContent=error;
alertBox.style.display='flex';
}
asyncfunctiondrawRoute(
//prettier-ignore
//@ts-ignore
route,isPrimaryRoute){
polylines=polylines.concat(route.createPolylines({
polylineOptions:isPrimaryRoute
?{map:map.innerMap,zIndex:1}
:{
map:map.innerMap,
strokeColor:'#669DF6',
strokeOpacity:0.5,
strokeWeight:8,
},
colorScheme:map.innerMap.get('colorScheme'),
}));
if(isPrimaryRoute){
markers=markers.concat(awaitroute.createWaypointAdvancedMarkers({
map:map.innerMap,
zIndex:1,
}));
if(route.viewport){
map.innerMap.fitBounds(route.viewport);
}
}
addRouteLabel(route,Math.floor(route.path.length/2));
}
//prettier-ignore
//@ts-ignore
functionaddRouteLabel(route,index){
constrouteTag=document.createElement('div');
routeTag.className='route-tag';
if(route.routeLabels && route.routeLabels.length > 0){
constp=document.createElement('p');
route.routeLabels.forEach((label,i)=>{
if(label.includes(RouteLabel.FUEL_EFFICIENT)){
routeTag.classList.add('eco');
}
if(label.includes(RouteLabel.DEFAULT_ROUTE_ALTERNATE)){
routeTag.classList.add('alternate');
}
if(label.includes(RouteLabel.SHORTER_DISTANCE)){
routeTag.classList.add('shorter-distance');
}
p.appendChild(document.createTextNode(label));
if(i < route.routeLabels.length-1){
p.appendChild(document.createElement('br'));
}
});
routeTag.appendChild(p);
}
constdetailsDiv=document.createElement('div');
detailsDiv.className='details';
if(route.localizedValues){
constdistanceP=document.createElement('p');
distanceP.textContent=`Distance: ${route.localizedValues.distance}`;
detailsDiv.appendChild(distanceP);
constdurationP=document.createElement('p');
durationP.textContent=`Duration: ${route.localizedValues.duration}`;
detailsDiv.appendChild(durationP);
}
if(route.travelAdvisory?.fuelConsumptionMicroliters){
constfuelP=document.createElement('p');
fuelP.textContent=`Fuel consumption: ${(route.travelAdvisory.fuelConsumptionMicroliters/1e6).toFixed(2)} L`;
detailsDiv.appendChild(fuelP);
}
routeTag.appendChild(detailsDiv);
constmarker=newAdvancedMarkerElement({
map:map.innerMap,
position:route.path[index],
content:routeTag,
zIndex:route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
?1
:undefined,
});
markers.push(marker);
}
functionclearMap(){
markers.forEach((marker)=>{
marker.map=null;
});
markers.length=0;
polylines.forEach((polyline)=>{
polyline.setMap(null);
});
polylines.length=0;
}
functionattachMapClickListener(){
if(!map||!map.innerMap){
return;
}
letinfoWindowAlert=document.getElementById('infowindow-alert');
if(!infoWindowAlert){
infoWindowAlert=document.createElement('div');
infoWindowAlert.id=infoWindowAlert.className='infowindow-alert';
infoWindowAlert.textContent='Lat/Lng are copied to clipboard';
}
constinfoWindow=newInfoWindow();
letcloseWindowTimeout;
map.innerMap.addListener('click',async(mapsMouseEvent)=>{
if(!mapsMouseEvent.latLng){
return;
}
infoWindow.close();
if(closeWindowTimeout){
clearTimeout(closeWindowTimeout);
}
infoWindow.setContent(infoWindowAlert);
infoWindow.setPosition({
lat:mapsMouseEvent.latLng.lat(),
lng:mapsMouseEvent.latLng.lng(),
});
awaitnavigator.clipboard.writeText(`${mapsMouseEvent.latLng.lat()},${mapsMouseEvent.latLng.lng()}`);
infoWindow.open(map.innerMap);
closeWindowTimeout=window.setTimeout(()=>{
infoWindow.close();
},2000);
});
}
functionattachTravelModeListener(){
consttravelMode=document.getElementById('travel-mode');
constroutingPreference=document.getElementById('routing-preference');
consttrafficAwarePolyline=document.getElementById('traffic-aware-polyline');
constecoRoutes=document.getElementById('eco-routes');
constemissionType=document.getElementById('emission-type');
travelMode.addEventListener('change',()=>{
// Toggle the Routing Preference selection and Traffic Aware Polyline
// selection for WALKING, BICYCLING, and TRANSIT modes.
if(travelMode.value==='WALKING'||
travelMode.value==='BICYCLING'||
travelMode.value==='TRANSIT'){
routingPreference.disabled=true;
routingPreference.value='';
}
else{
routingPreference.disabled=false;
routingPreference.value=
routingPreference.value||'TRAFFIC_UNAWARE';
}
toggleTrafficAwarePolyline();
// Toggle transit options for Transit mode
document.getElementById('transit-options').style.display=travelMode.value==='TRANSIT'?'flex':'none';
});
routingPreference.addEventListener('change',()=>{
toggleTrafficAwarePolyline();
});
ecoRoutes.addEventListener('change',()=>{
if(ecoRoutes.checked){
emissionType.disabled=false;
}
else{
emissionType.disabled=true;
}
});
functiontoggleTrafficAwarePolyline(){
if(!routingPreference.value||
routingPreference.value==='TRAFFIC_UNAWARE'){
trafficAwarePolyline.checked=false;
trafficAwarePolyline.disabled=true;
}
else{
trafficAwarePolyline.disabled=false;
}
}
}
functionattachAlertWindowListener(){
constalertBox=document.getElementById('alert');
constcloseBtn=alertBox.querySelector('.close');
closeBtn.addEventListener('click',()=>{
if(alertBox.style.display!=='none'){
alertBox.style.display='none';
}
});
}
functioninitializeLocationInputs(){
constoriginAutocomplete=newPlaceAutocompleteElement({
name:'origin_location',
});
constdestinationAutocomplete=newPlaceAutocompleteElement({
name:'destination_location',
});
[
[originAutocomplete,originAutocompleteSelection],
[destinationAutocomplete,destinationAutocompleteSelection],
].forEach(([autocomplete,autocompleteData])=>{
autocomplete.addEventListener('gmp-select',
//prettier-ignore
//@ts-ignore
async(event)=>{
autocompleteData.predictionText=event.placePrediction.text.text;
constplace=event.placePrediction.toPlace();
awaitplace.fetchFields({
fields:['location'],
});
autocompleteData.location=place.location;
});
});
document
.getElementById('origin-input')
?.appendChild(originAutocomplete);
document
.getElementById('destination-input')
?.appendChild(destinationAutocomplete);
}
functionattachDepartureTimeListener(){
constdepartureTime=document.getElementById('departure-time');
constutcOutput=document.getElementById('utc-output');
departureTime.addEventListener('change',()=>{
utcOutput.textContent=`UTC time: ${newDate(departureTime.value).toUTCString()}`;
});
}
}
window.addEventListener('load',init);

CSS

html,
body{
height:100%;
font-size:100%;
font-family:'Google Sans',sans-serif;
margin:0;
background-color:#fff;
}
*{
box-sizing:border-box;
}
h2,
h3{
color:#222;
font-style:normal;
font-weight:normal;
line-height:1.4;
margin-bottom:0.5rem;
margin-top:0.2rem;
}
h2{
font-weight:bold;
font-size:1rem;
}
h3{
font-size:0.8rem;
}
p{
font-size:0.8rem;
margin:000.6rem0;
}
label{
color:#4d4d4d;
display:inline-block;
margin:0;
position:relative;
z-index:2;
font-size:0.875rem;
}
input[type='text']{
height:50px;
width:100%;
padding:0.5rem;
border-radius:4px;
border:1pxsolid#ccc;
}
ul{
list-style:none;
padding-inline-start:0.25rem;
}
select{
appearance:none;
background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+);
background-position:100%center;
background-repeat:no-repeat;
padding-right:1.5rem;
&:disabled{
background-color:#ddd;
cursor:default;
}
&[multiple]{
height:auto;
}
}
select,
input[type='datetime-local']{
height:2.3125rem;
width:100%;
border-style:solid;
border-width:1px;
border-color:#ccc;
border-radius:4px;
padding:0.3rem;
font-family:inherit;
font-size:0.8rem;
}
button{
min-height:3rem;
min-width:3rem;
cursor:pointer;
font-family:inherit;
font-weight:normal;
font-size:0.875rem;
line-height:normal;
padding:01.5rem;
position:relative;
text-align:center;
text-decoration:none;
display:inline-block;
border-radius:4px;
transition:
background-color0.2s,
border0.2s;
&.button-primary{
background-color:#1a73e8;
color:#fff;
border:1pxsolid#dadce0;
&:hover{
background-color:#e8f0fe;
border-color:#d2e3fc;
color:#1a73e8;
}
}
&.button-secondary{
background-color:#fff;
color:#1a73e8;
border:none;
&:hover{
background-color:#1a73e8;
color:#fff;
}
}
&.close{
font-size:2rem;
}
}
hr{
border:1pxsolid#f4f0f0;
margin-inline:0;
}
section{
display:flex;
flex-direction:column;
padding:1.25rem1rem;
border-bottom:1pxsolid#ddd;
gap:0.5rem;
&:last-child{
border-bottom:none;
}
}
.main-content{
width:100%;
border:1pxsolid#e4e4e4;
border-radius:25px25px00;
}
.control-panel{
padding-top:20px;
overflow:scroll;
}
.map-container{
height:100%;
padding:0;
}
.map{
height:100%;
}
.row{
display:flex;
flex-flow:rowwrap;
align-items:flex-start;
gap:1rem;
&:not(:last-child){
margin-bottom:0.5rem;
}
}
gmp-place-autocomplete{
border:1pxsolid#ccc;
border-radius:4px;
}
gmp-advanced-marker:hover{
z-index:1;
}
.infowindow-alert{
font-size:0.8rem;
margin:0;
color:#fff;
}
.alert{
display:none;
position:fixed;
padding:1rem;
width:100%;
z-index:10;
background-color:#fff;
border-radius:25px25px00;
box-shadow:01px8px0px#e4e4e4;
flex-direction:row;
justify-content:space-between;
p{
padding:03rem01rem;
color:#f04124;
}
}
.route-tag{
background-color:#4285f4;
border-radius:8px;
font-size:14px;
padding:6px10px;
position:relative;
box-shadow:10px10px24px0rgba(0,0,0,0.3);
width:auto;
height:auto;
transition:0.3s;
color:#fff;
.details{
display:none;
p{
font-size:0.7em;
margin:05px;
color:#fff;
}
}
&::after{
content:'';
position:absolute;
left:50%;
top:100%;
transform:translate(-50%,0);
width:0;
height:0;
border-left:8pxsolidtransparent;
border-right:8pxsolidtransparent;
border-top:8pxsolid#4285f4;
}
&:hover{
p{
font-size:0.9em;
}
.details{
display:block;
}
}
&.eco{
background-color:#188038;
&::after{
border-top-color:#188038;
}
}
&.alternate{
background-color:white;
color:black;
.detailsp{
color:black;
}
&::after{
border-top-color:white;
}
}
&.shorter-distance{
background-color:purple;
&::after{
border-top-color:purple;
}
}
}
@mediaonlyscreenand(max-width:40em){
.control-panel{
width:100%;
height:500px;
overflow:scroll;
}
.map-container{
width:100%;
height:500px;
}
}
@mediaonlyscreenand(min-width:40.0625em)and(max-width:64em){
.control-panel{
width:100%;
overflow:auto;
}
.map-container{
width:100%;
height:800px;
}
}
@mediaonlyscreenand(min-width:64.0625em)and(max-width:100em){
.main-content{
display:flex;
height:100%;
}
.control-panel{
width:50%;
height:100%;
}
.map-container{
width:50%;
height:100%;
padding:1rem;
}
}
@mediaonlyscreenand(min-width:100.0625em){
.main-content{
display:flex;
height:100%;
}
.control-panel{
width:33.33333%;
height:100%;
}
.map-container{
width:66.66667%;
height:100%;
padding:1rem;
}
}
@mediaonlyscreen{
.heading-wrapper,
.route-option-name-wrapper{
width:calc(25%-0.5rem);
}
.location-input-wrapper,
.route-option-input{
width:calc(75%-0.5rem);
}
.departure-time-wrapper,
.eco-friendly-options-wrapper,
.location-options-wrapper,
.route-options-wrapper,
.transit-modes-wrapper,
.transit-routing-preference-wrapper,
.travel-mode-wrapper{
width:100%;
}
}
@mediaonlyscreenand(min-width:40.0625em){
.heading-wrapper,
.route-option-name-wrapper{
width:calc(25%-0.5rem);
}
.departure-time-wrapper,
.travel-mode-wrapper{
width:calc(33.33333%-0.5rem);
}
.eco-friendly-options-wrapper,
.transit-modes-wrapper,
.transit-routing-preference-wrapper,
.route-options-wrapper{
width:calc(50%-0.5rem);
}
.location-input-wrapper,
.route-option-input{
width:calc(75%-0.5rem);
}
.location-options-wrapper{
width:100%;
}
}

HTML

<html>
 <head>
 <title>Get routes</title>
 <link rel="stylesheet" type="text/css" href="./style.css" />
 <script type="module" src="./index.js"></script>
 </head>
 <body>
 <div class="main-content">
 <div class="alert" id="alert">
 <p>error</p>
 <button class="button-secondary close">&times;</button>
 </div>
 <div class="control-panel">
 <form id="compute-routes-form">
 <section>
 <h2>Input locations</h2>
 <div class="row">
 <div class="location-input-wrapper">
 <label class="text">Origin*</label>
 <div id="origin-input"></div>
 </div>
 <div class="heading-wrapper">
 <label for="heading_org" class="text"
 >Heading</label
 >
 <input
 type="text"
 id="heading_org"
 name="heading_org"
 value="" />
 </div>
 </div>
 <div class="row">
 <div class="location-options-wrapper">
 <input
 type="checkbox"
 id="origin_stopover"
 name="origin_stopover" />
 <label for="origin_stopover">Stopover</label>
 <input
 type="checkbox"
 id="side_of_road_org"
 name="origin_side_of_road" />
 <label for="side_of_road_org"
 >Side of Road</label
 >
 </div>
 </div>
 <hr />
 <div class="row">
 <div class="location-input-wrapper">
 <label class="text">Destination*</label>
 <div id="destination-input"></div>
 </div>
 <div class="heading-wrapper">
 <label for="heading_des" class="text"
 >Heading</label
 >
 <input
 type="text"
 id="heading_des"
 name="heading_des"
 value="" />
 </div>
 </div>
 <div class="row">
 <div class="location-options-wrapper">
 <input
 type="checkbox"
 id="destination_stopover"
 name="destination_stopover" />
 <label for="destination_stopover"
 >Stopover</label
 >
 <input
 type="checkbox"
 id="side_of_road_des"
 name="destination_side_of_road" />
 <label for="side_of_road_des"
 >Side of Road</label
 >
 </div>
 </div>
 </section>
 <section>
 <h2>Travel Mode</h2>
 <div class="row">
 <div class="travel-mode-wrapper">
 <select name="travel_mode" id="travel-mode">
 <option value="DRIVING">Driving</option>
 <option value="WALKING">Walking</option>
 <option value="BICYCLING">Bicycling</option>
 <option value="TWO_WHEELER">
 Two Wheeler (two-wheeled motorized
 vehicle)
 </option>
 <option value="TRANSIT">Transit</option>
 </select>
 </div>
 </div>
 <div
 class="row"
 id="transit-options"
 style="display: none">
 <div class="transit-modes-wrapper">
 <h3>Transit Modes</h3>
 <ul id="transitModes">
 <li>
 <input
 type="checkbox"
 name="bus"
 value="BUS"
 id="bus"
 checked />
 <label for="bus">Bus</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="subway"
 value="SUBWAY"
 id="subway"
 checked />
 <label for="subway">Subway</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="train"
 value="TRAIN"
 id="train"
 checked />
 <label for="train">Train</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="light_rail"
 value="LIGHT_RAIL"
 id="light_rail"
 checked />
 <label for="light_rail"
 >Light rail</label
 >
 </li>
 </ul>
 </div>
 <div class="transit-routing-preference-wrapper">
 <h3>Transit Routing Preference</h3>
 <select
 name="transit_preference"
 id="transitPreference">
 <option value=""></option>
 <option value="LESS_WALKING">
 Less walking
 </option>
 <option value="FEWER_TRANSFERS">
 Fewer transfers
 </option>
 </select>
 </div>
 </div>
 </section>
 <section>
 <h2>Departure Time (Your local time)</h2>
 <p>
 Choose your <b>local time</b>. The selected time
 will be converted to <b>UTC format time</b>.
 </p>
 <p>
 If you set the departure time, the routing
 preference has to be either TRAFFIC_AWARE or
 TRAFFIC_AWARE_OPTIMAL. TRAFFIC_AWARE_OPTIMAL
 calculates best routes by factoring in real-time
 road conditions, including closures.
 </p>
 <div class="row">
 <div class="departure-time-wrapper">
 <input
 type="datetime-local"
 id="departure-time"
 name="departure_time" />
 <p id="utc-output"></p>
 </div>
 </div>
 </section>
 <section>
 <h2>Route Options</h2>
 <div class="row">
 <div class="route-options-wrapper">
 <div class="row">
 <h3 class="route-option-name-wrapper">
 Polyline Quality
 </h3>
 <select
 class="route-option-input"
 name="polyline_quality"
 id="polyline_quality">
 <option value=""></option>
 <option value="HIGH_QUALITY">
 High quality
 </option>
 <option value="OVERVIEW">
 Overview
 </option>
 </select>
 </div>
 <div class="row">
 <h3 class="route-option-name-wrapper">
 Traffic Awareness
 </h3>
 <select
 class="route-option-input"
 name="routing_preference"
 id="routing-preference">
 <option value=""></option>
 <option value="TRAFFIC_UNAWARE">
 Traffic unaware
 </option>
 <option value="TRAFFIC_AWARE">
 Traffic aware
 </option>
 <option value="TRAFFIC_AWARE_OPTIMAL">
 Traffic aware optimal (best routes
 with accurate ETA)
 </option>
 </select>
 </div>
 <div class="row">
 <h3 class="route-option-name-wrapper">
 Traffic Aware Polyline
 </h3>
 <div class="route-option-input">
 <input
 type="checkbox"
 name="traffic_aware_polyline"
 id="traffic-aware-polyline"
 disabled />
 <label
 for="traffic-aware-polyline"></label>
 </div>
 </div>
 </div>
 <div class="route-options-wrapper">
 <h3>Route Modifiers</h3>
 <ul>
 <li>
 <input
 type="checkbox"
 name="avoid_tolls"
 value="avoid_tolls"
 id="avoid_tolls" />
 <label for="avoid_tolls"
 >Avoid tolls</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="avoid_highways"
 value="avoid_highways"
 id="avoid_highways" />
 <label for="avoid_highways"
 >Avoid highways</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="avoid_ferries"
 value="avoid_ferries"
 id="avoid_ferries" />
 <label for="avoid_ferries"
 >Avoid ferries</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="avoid_indoor"
 value="avoid_indoor"
 id="avoid_indoor" />
 <label for="avoid_indoor"
 >Avoid indoor</label
 >
 </li>
 </ul>
 </div>
 </div>
 </section>
 <section>
 <h2>Reference routes</h2>
 <div class="row">
 <div>
 <input
 type="checkbox"
 name="compute_alternative_routes"
 id="compute_alternative_routes" />
 <label for="compute_alternative_routes"
 >Alternative Routes</label
 >
 </div>
 </div>
 <div class="row">
 <div>
 <input
 type="checkbox"
 name="shorter_distance"
 id="shorter_distance" />
 <label for="shorter_distance"
 >Shorter Distance Routes</label
 >
 </div>
 </div>
 <hr />
 <div class="row">
 <div class="eco-friendly-options-wrapper">
 <div>
 <input
 type="checkbox"
 name="eco_routes"
 id="eco-routes" />
 <label for="eco-routes"
 >Eco-friendly Routes</label
 >
 </div>
 </div>
 <div
 class="eco-friendly-options-wrapper"
 id="enginetype">
 <h3>Emission Type</h3>
 <select
 name="emission_type"
 id="emission-type"
 disabled>
 <option value="GASOLINE">Gasoline</option>
 <option value="ELECTRIC">Electric</option>
 <option value="HYBRID">Hybrid</option>
 <option value="DIESEL">Diesel</option>
 </select>
 </div>
 </div>
 </section>
 <section>
 <h2>Fields</h2>
 <div class="row" id="field-mask">
 <div>
 <h3>Fields</h3>
 <ul id="fields">
 <li>
 <input
 type="checkbox"
 name="route_labels"
 value="routeLabels"
 id="route_labels"
 checked
 disabled />
 <label for="route_labels"
 >routeLabels</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="legs"
 value="legs"
 id="legs"
 checked />
 <label for="legs">legs</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="distance_meters"
 value="distanceMeters"
 id="distance_meters" />
 <label for="distance_meters"
 >distanceMeters</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="duration_millis"
 value="durationMillis"
 id="duration_millis" />
 <label for="duration_millis"
 >durationMillis</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="static_duration_millis"
 value="staticDurationMillis"
 id="static_duration_millis" />
 <label for="static_duration_millis"
 >staticDurationMillis</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="path"
 value="path"
 id="path"
 checked
 disabled />
 <label for="path">path</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="polyline_details"
 value="polylineDetails"
 id="polyline_details" />
 <label for="polyline_details"
 >polylineDetails</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="description"
 value="description"
 id="description" />
 <label for="description"
 >description</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="warnings"
 value="warnings"
 id="warnings" />
 <label for="warnings">warnings</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="viewport"
 value="viewport"
 id="viewport"
 checked
 disabled />
 <label for="viewport">viewport</label>
 </li>
 <li>
 <input
 type="checkbox"
 name="travel_advisory"
 value="travelAdvisory"
 id="travel_advisory" />
 <label for="travel_advisory"
 >travelAdvisory</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="optimized_intermediate_waypoint_indices"
 value="optimizedIntermediateWaypointIndices"
 id="optimized_intermediate_waypoint_indices" />
 <label
 for="optimized_intermediate_waypoint_indices"
 >optimizedIntermediateWaypointIndices</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="localized_values"
 value="localizedValues"
 id="localized_values"
 checked
 disabled />
 <label for="localized_values"
 >localizedValues</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="route_token"
 value="routeToken"
 id="route_token" />
 <label for="route_token"
 >routeToken</label
 >
 </li>
 <li>
 <input
 type="checkbox"
 name="speed_paths"
 value="speedPaths"
 id="speed_paths" />
 <label for="speed_paths"
 >speedPaths</label
 >
 </li>
 </ul>
 </div>
 </div>
 </section>
 <section>
 <div class="row">
 <button class="button-primary" type="submit">
 Get routes
 </button>
 </div>
 </section>
 </form>
 </div>
 <div class="map-container">
 <gmp-map
 id="map"
 class="map"
 center="-34.397, 150.644"
 zoom="4"
 map-id="DEMO_MAP_ID"></gmp-map>
 </div>
 </div>
 <!-- prettier-ignore -->
 <script>(g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })
 ({ key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "beta" });</script>
 </body>
</html>

Try Sample

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年11月21日 UTC.