路线演示

欧洲经济区 (EEA) 开发者

在“路线”演示中,您可以将出发地和目的地指定为纬度/经度坐标对或地点 ID。如需复制纬度/经度坐标,请在地图上找到并点击某个位置,然后将该位置粘贴到表单中。

选择获取路线后,演示会显示 computeRoutes 方法的响应,即地图上的路线。

查看完整的示例源代码

通过以下演示,您可以尝试创建各种不同的路线。 点击地图即可复制某个位置的纬度/经度坐标。将坐标粘贴到表单中以获取路线。

TypeScript

let markers: google.maps.marker.AdvancedMarkerElement[] = [];
let polylines: google.maps.Polyline[] = [];
let waypointInfoWindow: google.maps.InfoWindow | null = null;

interface PlaceAutocompleteSelection {
    predictionText: string | null;
    location: google.maps.LatLng | null;
}

const originAutocompleteSelection: PlaceAutocompleteSelection = {
    predictionText: null,
    location: null,
};
const destinationAutocompleteSelection: PlaceAutocompleteSelection = {
    predictionText: null,
    location: null,
};

async function init() {
    const [
        { InfoWindow },
        { AdvancedMarkerElement },
        //prettier-ignore
        //@ts-ignore
        { PlaceAutocompleteElement },
        //prettier-ignore
        //@ts-ignore
        { ComputeRoutesExtraComputation, ReferenceRoute, Route, RouteLabel },
    ] = await Promise.all([
        google.maps.importLibrary('maps') as Promise<google.maps.MapsLibrary>,
        google.maps.importLibrary(
            'marker'
        ) as Promise<google.maps.MarkerLibrary>,
        google.maps.importLibrary(
            'places'
        ) as Promise<google.maps.PlacesLibrary>,
        google.maps.importLibrary(
            'routes'
        ) as Promise<google.maps.RoutesLibrary>,
    ]);

    const map = document.getElementById('map') as google.maps.MapElement;

    attachSubmitListener();
    initializeLocationInputs();
    attachMapClickListener();
    attachTravelModeListener();
    attachAlertWindowListener();
    attachDepartureTimeListener();

    function attachSubmitListener() {
        const computeRoutesForm = document.getElementById(
            'compute-routes-form'
        ) as HTMLFormElement;

        computeRoutesForm.addEventListener('submit', (event) => {
            event.preventDefault();
            sendRequest(new FormData(computeRoutesForm));
        });
    }

    async function sendRequest(formData: FormData) {
        clearMap();

        try {
            const { routes } = await Route.computeRoutes(
                buildComputeRoutesJsRequest(formData)
            );

            if (!routes) {
                console.log('No routes returned.');
                return;
            }

            console.log('Routes:');
            routes.forEach((route) => {
                console.log(route.toJSON());
            });

            await Promise.all(
                routes.map((route) =>
                    drawRoute(
                        route,
                        !!route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
                    )
                )
            );
        } catch (error: unknown) {
            console.error(error);
            setErrorMessage((error as Error).message || 'Unknown error.');
        }
    }

    function buildComputeRoutesJsRequest(
        formData: FormData
        //prettier-ignore
        //@ts-ignore
    ): google.maps.routes.ComputeRoutesRequest {
        const travelMode =
            (formData.get('travel_mode') as string) === ''
                ? undefined
                : (formData.get('travel_mode') as google.maps.TravelMode);
        //prettier-ignore
        //@ts-ignore
        const extraComputations: google.maps.routes.ComputeRoutesExtraComputation[] =
      [];
        //prettier-ignore
        //@ts-ignore
        const requestedReferenceRoutes: google.maps.routes.ReferenceRoute[] = [];
        //prettier-ignore
        //@ts-ignore
        const transitPreference: google.maps.routes.TransitPreference = {};

        const request = {
            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 as HTMLInputElement).value
            ),
            travelMode: travelMode as google.maps.TravelMode,
            routingPreference:
                formData.get('routing_preference') === ''
                    ? undefined
                    : (formData.get(
                          'routing_preference'
                          //prettier-ignore
                          //@ts-ignore
                      ) as google.maps.routes.RoutingPreference),
            polylineQuality:
                formData.get('polyline_quality') === ''
                    ? undefined
                    : (formData.get(
                          'polyline_quality'
                          //prettier-ignore
                          //@ts-ignore
                      ) as google.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') as string) === ''
                    ? undefined
                    : new Date(formData.get('departure_time') as string),
            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 as google.maps.routes.RouteModifiers).vehicleInfo =
                {
                    emissionType: formData.get(
                        'emission_type'
                        //prettier-ignore
                        //@ts-ignore
                    ) as google.maps.routes.VehicleEmissionType,
                };
        }

        if (travelMode === google.maps.TravelMode.TRANSIT) {
            const selectedTransitModes = document.querySelectorAll(
                'ul#transitModes li input[type="checkbox"]:checked'
            );
            transitPreference.allowedTransitModes = Array.from(
                selectedTransitModes,
                (input) =>
                    (input as HTMLInputElement).value as google.maps.TransitMode
            );
            transitPreference.routingPreference =
                formData.get('transit_preference') === ''
                    ? undefined
                    : (formData.get(
                          'transit_preference'
                      ) as google.maps.TransitRoutePreference);
        }

        return request;
    }

    function buildComputeRoutesLocation(
        autocompleteSelection: PlaceAutocompleteSelection,
        locationInput?: FormDataEntryValue | null,
        headingInput?: FormDataEntryValue | null,
        travelModeInput?: FormDataEntryValue | null
        //prettier-ignore
        //@ts-ignore
    ): string | google.maps.routes.DirectionalLocationLiteral {
        if (!locationInput) {
            throw new Error('Location is required.');
        }

        const latLngRegex = /^-?\d+(\.\d+)?,\s*-?\d+(\.\d+)?$/;
        const location = locationInput as string;
        const heading =
            headingInput && travelModeInput !== 'TRANSIT'
                ? Number(headingInput as string)
                : 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,
            };
        } else if (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
        return location;
    }

    function setErrorMessage(error: string) {
        const alertBox = document.getElementById('alert') as HTMLDivElement;
        alertBox.querySelector('p')!.textContent = error;
        alertBox.style.display = 'flex';
    }

    async function drawRoute(
        //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(
                await route.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
    function addRouteLabel(route: google.maps.routes.Route, index: number) {
    const routeTag = document.createElement('div');
    routeTag.className = 'route-tag';

    if (route.routeLabels && route.routeLabels.length > 0) {
      const p = 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);
    }

    const detailsDiv = document.createElement('div');
    detailsDiv.className = 'details';

    if (route.localizedValues) {
      const distanceP = document.createElement('p');
      distanceP.textContent = `Distance: ${route.localizedValues.distance!}`;
      detailsDiv.appendChild(distanceP);

      const durationP = document.createElement('p');
      durationP.textContent = `Duration: ${route.localizedValues.duration}`!;
      detailsDiv.appendChild(durationP);
    }

    if (route.travelAdvisory?.fuelConsumptionMicroliters) {
      const fuelP = document.createElement('p');
      fuelP.textContent = `Fuel consumption: ${(
        route.travelAdvisory.fuelConsumptionMicroliters / 1e6
      ).toFixed(2)} L`;
      detailsDiv.appendChild(fuelP);
    }

    routeTag.appendChild(detailsDiv);

    const marker = new AdvancedMarkerElement({
      map: map.innerMap,
      position: route.path![index],
      content: routeTag,
      zIndex: route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
        ? 1
        : undefined,
    });
    markers.push(marker);
  }

    function clearMap() {
        markers.forEach((marker) => {
            marker.map = null;
        });
        markers.length = 0;

        polylines.forEach((polyline) => {
            polyline.setMap(null);
        });
        polylines.length = 0;
    }

    function attachMapClickListener() {
        if (!map || !map.innerMap) {
            return;
        }

        let infoWindowAlert = document.getElementById('infowindow-alert');
        if (!infoWindowAlert) {
            infoWindowAlert = document.createElement('div');
            infoWindowAlert.id = infoWindowAlert.className = 'infowindow-alert';
            infoWindowAlert.textContent = 'Lat/Lng are copied to clipboard';
        }

        const infoWindow = new InfoWindow();
        let closeWindowTimeout: 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(),
                });

                await navigator.clipboard.writeText(
                    `${mapsMouseEvent.latLng.lat()},${mapsMouseEvent.latLng.lng()}`
                );

                infoWindow.open(map.innerMap);
                closeWindowTimeout = window.setTimeout(() => {
                    infoWindow.close();
                }, 2000);
            }
        );
    }

    function attachTravelModeListener() {
        const travelMode = document.getElementById(
            'travel-mode'
        ) as HTMLSelectElement;
        const routingPreference = document.getElementById(
            'routing-preference'
        ) as HTMLSelectElement;
        const trafficAwarePolyline = document.getElementById(
            'traffic-aware-polyline'
        ) as HTMLInputElement;
        const ecoRoutes = document.getElementById(
            'eco-routes'
        ) as HTMLInputElement;
        const emissionType = document.getElementById(
            'emission-type'
        ) as HTMLSelectElement;

        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') as HTMLElement
            ).style.display = travelMode.value === 'TRANSIT' ? 'flex' : 'none';
        });

        routingPreference.addEventListener('change', () => {
            toggleTrafficAwarePolyline();
        });

        ecoRoutes.addEventListener('change', () => {
            if (ecoRoutes.checked) {
                emissionType.disabled = false;
            } else {
                emissionType.disabled = true;
            }
        });

        function toggleTrafficAwarePolyline() {
            if (
                !routingPreference.value ||
                routingPreference.value === 'TRAFFIC_UNAWARE'
            ) {
                trafficAwarePolyline.checked = false;
                trafficAwarePolyline.disabled = true;
            } else {
                trafficAwarePolyline.disabled = false;
            }
        }
    }

    function attachAlertWindowListener() {
        const alertBox = document.getElementById('alert') as HTMLDivElement;
        const closeBtn = alertBox.querySelector('.close') as HTMLButtonElement;
        closeBtn.addEventListener('click', () => {
            if (alertBox.style.display !== 'none') {
                alertBox.style.display = 'none';
            }
        });
    }

    function initializeLocationInputs() {
        const originAutocomplete = new PlaceAutocompleteElement({
            name: 'origin_location',
        });
        const destinationAutocomplete = new PlaceAutocompleteElement({
            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;

          const place = event.placePrediction.toPlace();
          await place.fetchFields({
            fields: ['location'],
          });
          autocompleteData.location = place.location;
        }
            );
        });

        document
            .getElementById('origin-input')
            ?.appendChild(originAutocomplete);
        document
            .getElementById('destination-input')
            ?.appendChild(destinationAutocomplete);
    }

    function attachDepartureTimeListener() {
        const departureTime = document.getElementById(
            'departure-time'
        ) as HTMLInputElement;
        const utcOutput = document.getElementById(
            'utc-output'
        ) as HTMLParagraphElement;
        departureTime.addEventListener('change', () => {
            utcOutput.textContent = `UTC time: ${new Date(
                departureTime.value
            ).toUTCString()}`;
        });
    }
}

window.addEventListener('load', init);

JavaScript

let markers = [];
let polylines = [];
let waypointInfoWindow = null;
const originAutocompleteSelection = {
    predictionText: null,
    location: null,
};
const destinationAutocompleteSelection = {
    predictionText: null,
    location: null,
};
async function init() {
    const [{ InfoWindow }, { AdvancedMarkerElement }, 
    //prettier-ignore
    //@ts-ignore
    { PlaceAutocompleteElement }, 
    //prettier-ignore
    //@ts-ignore
    { ComputeRoutesExtraComputation, ReferenceRoute, Route, RouteLabel },] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('routes'),
    ]);
    const map = document.getElementById('map');
    attachSubmitListener();
    initializeLocationInputs();
    attachMapClickListener();
    attachTravelModeListener();
    attachAlertWindowListener();
    attachDepartureTimeListener();
    function attachSubmitListener() {
        const computeRoutesForm = document.getElementById('compute-routes-form');
        computeRoutesForm.addEventListener('submit', (event) => {
            event.preventDefault();
            sendRequest(new FormData(computeRoutesForm));
        });
    }
    async function sendRequest(formData) {
        clearMap();
        try {
            const { routes } = await Route.computeRoutes(buildComputeRoutesJsRequest(formData));
            if (!routes) {
                console.log('No routes returned.');
                return;
            }
            console.log('Routes:');
            routes.forEach((route) => {
                console.log(route.toJSON());
            });
            await Promise.all(routes.map((route) => drawRoute(route, !!route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE))));
        }
        catch (error) {
            console.error(error);
            setErrorMessage(error.message || 'Unknown error.');
        }
    }
    function buildComputeRoutesJsRequest(formData
    //prettier-ignore
    //@ts-ignore
    ) {
        const travelMode = formData.get('travel_mode') === ''
            ? undefined
            : formData.get('travel_mode');
        //prettier-ignore
        //@ts-ignore
        const extraComputations = [];
        //prettier-ignore
        //@ts-ignore
        const requestedReferenceRoutes = [];
        //prettier-ignore
        //@ts-ignore
        const transitPreference = {};
        const request = {
            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
                : new Date(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) {
            const selectedTransitModes = 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');
        }
        return request;
    }
    function buildComputeRoutesLocation(autocompleteSelection, locationInput, headingInput, travelModeInput
    //prettier-ignore
    //@ts-ignore
    ) {
        if (!locationInput) {
            throw new Error('Location is required.');
        }
        const latLngRegex = /^-?\d+(\.\d+)?,\s*-?\d+(\.\d+)?$/;
        const location = locationInput;
        const heading = 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,
            };
        }
        else if (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
        return location;
    }
    function setErrorMessage(error) {
        const alertBox = document.getElementById('alert');
        alertBox.querySelector('p').textContent = error;
        alertBox.style.display = 'flex';
    }
    async function drawRoute(
    //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(await route.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
    function addRouteLabel(route, index) {
        const routeTag = document.createElement('div');
        routeTag.className = 'route-tag';
        if (route.routeLabels && route.routeLabels.length > 0) {
            const p = 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);
        }
        const detailsDiv = document.createElement('div');
        detailsDiv.className = 'details';
        if (route.localizedValues) {
            const distanceP = document.createElement('p');
            distanceP.textContent = `Distance: ${route.localizedValues.distance}`;
            detailsDiv.appendChild(distanceP);
            const durationP = document.createElement('p');
            durationP.textContent = `Duration: ${route.localizedValues.duration}`;
            detailsDiv.appendChild(durationP);
        }
        if (route.travelAdvisory?.fuelConsumptionMicroliters) {
            const fuelP = document.createElement('p');
            fuelP.textContent = `Fuel consumption: ${(route.travelAdvisory.fuelConsumptionMicroliters / 1e6).toFixed(2)} L`;
            detailsDiv.appendChild(fuelP);
        }
        routeTag.appendChild(detailsDiv);
        const marker = new AdvancedMarkerElement({
            map: map.innerMap,
            position: route.path[index],
            content: routeTag,
            zIndex: route.routeLabels?.includes(RouteLabel.DEFAULT_ROUTE)
                ? 1
                : undefined,
        });
        markers.push(marker);
    }
    function clearMap() {
        markers.forEach((marker) => {
            marker.map = null;
        });
        markers.length = 0;
        polylines.forEach((polyline) => {
            polyline.setMap(null);
        });
        polylines.length = 0;
    }
    function attachMapClickListener() {
        if (!map || !map.innerMap) {
            return;
        }
        let infoWindowAlert = document.getElementById('infowindow-alert');
        if (!infoWindowAlert) {
            infoWindowAlert = document.createElement('div');
            infoWindowAlert.id = infoWindowAlert.className = 'infowindow-alert';
            infoWindowAlert.textContent = 'Lat/Lng are copied to clipboard';
        }
        const infoWindow = new InfoWindow();
        let closeWindowTimeout;
        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(),
            });
            await navigator.clipboard.writeText(`${mapsMouseEvent.latLng.lat()},${mapsMouseEvent.latLng.lng()}`);
            infoWindow.open(map.innerMap);
            closeWindowTimeout = window.setTimeout(() => {
                infoWindow.close();
            }, 2000);
        });
    }
    function attachTravelModeListener() {
        const travelMode = document.getElementById('travel-mode');
        const routingPreference = document.getElementById('routing-preference');
        const trafficAwarePolyline = document.getElementById('traffic-aware-polyline');
        const ecoRoutes = document.getElementById('eco-routes');
        const emissionType = 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;
            }
        });
        function toggleTrafficAwarePolyline() {
            if (!routingPreference.value ||
                routingPreference.value === 'TRAFFIC_UNAWARE') {
                trafficAwarePolyline.checked = false;
                trafficAwarePolyline.disabled = true;
            }
            else {
                trafficAwarePolyline.disabled = false;
            }
        }
    }
    function attachAlertWindowListener() {
        const alertBox = document.getElementById('alert');
        const closeBtn = alertBox.querySelector('.close');
        closeBtn.addEventListener('click', () => {
            if (alertBox.style.display !== 'none') {
                alertBox.style.display = 'none';
            }
        });
    }
    function initializeLocationInputs() {
        const originAutocomplete = new PlaceAutocompleteElement({
            name: 'origin_location',
        });
        const destinationAutocomplete = new PlaceAutocompleteElement({
            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;
                const place = event.placePrediction.toPlace();
                await place.fetchFields({
                    fields: ['location'],
                });
                autocompleteData.location = place.location;
            });
        });
        document
            .getElementById('origin-input')
            ?.appendChild(originAutocomplete);
        document
            .getElementById('destination-input')
            ?.appendChild(destinationAutocomplete);
    }
    function attachDepartureTimeListener() {
        const departureTime = document.getElementById('departure-time');
        const utcOutput = document.getElementById('utc-output');
        departureTime.addEventListener('change', () => {
            utcOutput.textContent = `UTC time: ${new Date(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: 0 0 0.6rem 0;
}

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: 1px solid #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: 0 1.5rem;
    position: relative;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    border-radius: 4px;
    transition:
        background-color 0.2s,
        border 0.2s;

    &.button-primary {
        background-color: #1a73e8;
        color: #fff;
        border: 1px solid #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: 1px solid #f4f0f0;
    margin-inline: 0;
}

section {
    display: flex;
    flex-direction: column;
    padding: 1.25rem 1rem;
    border-bottom: 1px solid #ddd;
    gap: 0.5rem;

    &:last-child {
        border-bottom: none;
    }
}

.main-content {
    width: 100%;
    border: 1px solid #e4e4e4;
    border-radius: 25px 25px 0 0;
}

.control-panel {
    padding-top: 20px;
    overflow: scroll;
}

.map-container {
    height: 100%;
    padding: 0;
}

.map {
    height: 100%;
}

.row {
    display: flex;
    flex-flow: row wrap;
    align-items: flex-start;
    gap: 1rem;

    &:not(:last-child) {
        margin-bottom: 0.5rem;
    }
}

gmp-place-autocomplete {
    border: 1px solid #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: 25px 25px 0 0;
    box-shadow: 0 1px 8px 0px #e4e4e4;
    flex-direction: row;
    justify-content: space-between;

    p {
        padding: 0 3rem 0 1rem;
        color: #f04124;
    }
}

.route-tag {
    background-color: #4285f4;
    border-radius: 8px;
    font-size: 14px;
    padding: 6px 10px;
    position: relative;
    box-shadow: 10px 10px 24px 0 rgba(0, 0, 0, 0.3);
    width: auto;
    height: auto;
    transition: 0.3s;
    color: #fff;

    .details {
        display: none;

        p {
            font-size: 0.7em;
            margin: 0 5px;
            color: #fff;
        }
    }

    &::after {
        content: '';
        position: absolute;
        left: 50%;
        top: 100%;
        transform: translate(-50%, 0);
        width: 0;
        height: 0;
        border-left: 8px solid transparent;
        border-right: 8px solid transparent;
        border-top: 8px solid #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;

        .details p {
            color: black;
        }

        &::after {
            border-top-color: white;
        }
    }

    &.shorter-distance {
        background-color: purple;

        &::after {
            border-top-color: purple;
        }
    }
}

@media only screen and (max-width: 40em) {
    .control-panel {
        width: 100%;
        height: 500px;
        overflow: scroll;
    }

    .map-container {
        width: 100%;
        height: 500px;
    }
}

@media only screen and (min-width: 40.0625em) and (max-width: 64em) {
    .control-panel {
        width: 100%;
        overflow: auto;
    }

    .map-container {
        width: 100%;
        height: 800px;
    }
}

@media only screen and (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;
    }
}

@media only screen and (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;
    }
}

@media only screen {
    .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%;
    }
}

@media only screen and (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>

试用示例