JavaScript
let map; async function init() { const { Map3DElement } = await google.maps.importLibrary('maps3d'); map = new Map3DElement({ center: { lat: 0, lng: 0, altitude: 16000000 }, tilt: 0, range: 0, heading: 0, roll: 0, mode: 'HYBRID', }); document.body.append(map); void initAutocomplete(); } async function initAutocomplete() { const { PlaceAutocompleteElement } = await google.maps.importLibrary('places'); const placeAutocomplete = new PlaceAutocompleteElement(); placeAutocomplete.id = 'place-autocomplete-input'; const card = document.getElementById('pac-container'); card.appendChild(placeAutocomplete); placeAutocomplete.addEventListener( 'gmp-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); await place.fetchFields({ fields: ['displayName', 'location', 'id'], }); // If the place has a geometry, then present it on a map. if (!place.location) { window.alert('No viewport for input: ' + place.displayName); return; } void flyToPlace(place); } ); } const flyToPlace = async (place) => { const { Marker3DElement } = await google.maps.importLibrary('maps3d'); const location = place.location; // We need to find the elevation for the point so we place the marker at 50m above the elevation. const elevation = await getElevationforPoint(location, place); const marker = new Marker3DElement({ position: { lat: location.lat(), lng: location.lng(), altitude: elevation + 50, }, altitudeMode: 'ABSOLUTE', extruded: true, label: place.displayName, }); // Add the marker. map.append(marker); // Fly to the marker. map.flyCameraTo({ endCamera: { center: { lat: location.lat(), lng: location.lng(), altitude: elevation + 50, }, tilt: 65, heading: 0, range: 1000, }, durationMillis: 10000, }); }; async function getElevationforPoint(location, place) { const defaultElevation = 10; const { ElevationService } = await google.maps.importLibrary('elevation'); // Get place elevation using the ElevationService. const elevatorService = new ElevationService(); const elevationResponse = await elevatorService.getElevationForLocations({ locations: [location], }); if (!elevationResponse?.results.length) { window.alert( `Insufficient elevation data for place: ${place.displayName}` ); return defaultElevation; } const elevation = elevationResponse.results[0].elevation || defaultElevation; return elevation; } void init();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ html, map { height: 100%; } body { height: 100%; margin: 0; padding: 0; } .pac-controls { display: inline-block; padding: 0px 11px; } .pac-controls label { font-family: Roboto, sans-serif; font-size: 13px; font-weight: 300; } .pac-card { background-color: #fff; border: 0; border-radius: 4px; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3); margin: 10px; padding: 0 0.5em; font: 400 18px Roboto, Arial, sans-serif; font-family: Roboto, sans-serif; padding: 0; position: absolute; left: 10px; top: 10px; z-index: 99; } #pac-container { padding-top: 12px; padding-bottom: 12px; margin-right: 12px; border-radius: 2px; width: 412px; } #pac-input { background-color: #fff; font-family: Roboto, sans-serif; font-size: 15px; font-weight: 300; margin-left: 12px; padding: 0 11px 0 13px; text-overflow: ellipsis; width: 400px; } #pac-input:focus { border-color: #4d90fe; } #title { color: #fff; background-color: #4d90fe; font-size: 14px; font-weight: 500; padding: 6px 12px; } #place-autocomplete-card { background-color: #fff; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; margin: 10px; padding: 5px; font-family: Roboto, sans-serif; font-size: large; font-weight: bold; } gmp-place-autocomplete { padding-left: 10px; width: 405px; z-index: 100; }
HTML
<html>
<head>
<title>Map</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: "GOOGLE_MAPS_API_KEY"
});
</script>
</head>
<body>
<div id="map"></div>
<div class="pac-card" id="pac-card">
<div id="title">Navigate to a place</div>
<div id="pac-container"></div>
</div>
</body>
</html>Clone Sample
Git and Node.js are required to run this sample locally. Follow these instructions to install Node.js and NPM. You will also need a Google Maps API key.
The following commands clone the repository, install dependencies, and copy the environment file.
git clone https://github.com/googlemaps-samples/js-api-samples.gitcd js-api-samplesnpm icp .env.template .env
Once you copy the environment file, make sure to open the .env file and replace <Insert your own development API key here> with your actual API key before starting the sample.
cd samples/3d-places-autocompletenpm start