路线演示

欧洲经济区 (EEA) 开发者

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

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

查看完整的示例源代码

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

TypeScript

let markers: google.maps.marker.AdvancedMarkerElement[] = [];
let polylines: google.maps.Polyline[] = [];

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 },
        // @ts-expect-error - currently missing. bug fix pending
        { PlaceAutocompleteElement },
        { 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') 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();
            void 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
    ): google.maps.routes.ComputeRoutesRequest {
        const travelMode =
            (formData.get('travel_mode') as string) === ''
                ? undefined
                : formData.get('travel_mode');
        const extraComputations: google.maps.routes.ComputeRoutesExtraComputation[] =
            [];
        const requestedReferenceRoutes: google.maps.routes.ReferenceRoute[] =
            [];
        const transitPreference: google.maps.routes.TransitPreference = {};

        const request: google.maps.routes.ComputeRoutesRequest = {
            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'
                      ) as google.maps.routes.RoutingPreference),
            polylineQuality:
                formData.get('polyline_quality') === ''
                    ? undefined
                    : (formData.get(
                          'polyline_quality'
                      ) 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
            );
            request.routeModifiers!.vehicleInfo = {
                emissionType: formData.get(
                    'emission_type'
                ) as google.maps.routes.VehicleEmissionType,
            };
        }

        if (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
    ): 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)
                : 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(
        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));
    }

    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')!;
        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',
                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()}`;
        });
    }
}

void init();

JavaScript

let markers = [];
let polylines = [];

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

async function init() {
    const [
        { InfoWindow },
        { AdvancedMarkerElement },
        // @ts-expect-error - currently missing. bug fix pending
        { PlaceAutocompleteElement },
        { 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();
            void 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) {
        const travelMode =
            formData.get('travel_mode') === ''
                ? undefined
                : formData.get('travel_mode');
        const extraComputations = [];
        const requestedReferenceRoutes = [];
        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'),
            polylineQuality:
                formData.get('polyline_quality') === ''
                    ? undefined
                    : formData.get('polyline_quality'),
            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
            );
            request.routeModifiers.vehicleInfo = {
                emissionType: formData.get('emission_type'),
            };
        }

        if (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
    ) {
        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(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));
    }

    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', 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()}`;
        });
    }
}

void 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>
        <script>
            // prettier-ignore
            (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" 
            });
        </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>
    </body>
</html>

试用示例