The following 3D map modes are available in the Maps JavaScript API:
-
ROADMAPdisplays the default road map view with basemap labels. -
SATELLITEdisplays a photorealistic map based on aerial imagery. -
HYBRIDdisplays the satellite map view with basemap labels.
Here's an example of the 3D map in ROADMAP
mode:
TypeScript
async function init () { const { Map3DElement } = await google . maps . importLibrary ( 'maps3d' ); const map = new Map3DElement ({ center : { lat : 37.79334535092104 , lng : - 122.400742086205 , altitude : 0 , }, range : 2400 , tilt : 65 , heading : 0 , mode : 'ROADMAP' , internalUsageAttributionIds : [ 'gmp_git_jsapisamples_v1_3d-rendering' ], }); document . body . append ( map ); // Create the controls container const controls = document . createElement ( 'div' ); controls . id = 'controls' ; controls . classList . add ( 'map-mode-control' ); // Create the select element const selector = document . createElement ( 'select' ); selector . id = 'map-mode' ; const modes = [ 'ROADMAP' , 'SATELLITE' , 'HYBRID' ]; modes . forEach (( modeName ) = > { const option = document . createElement ( 'option' ); option . value = modeName ; option . textContent = modeName ; if ( modeName === 'ROADMAP' ) { option . selected = true ; } selector . appendChild ( option ); }); selector . addEventListener ( 'change' , ( event ) = > { map . mode = ( event . target as HTMLSelectElement ). value ; }); controls . appendChild ( selector ); document . body . appendChild ( controls ); } init ();
JavaScript
async function init () { const { Map3DElement } = await google . maps . importLibrary ( 'maps3d' ); const map = new Map3DElement ({ center : { lat : 37.79334535092104 , lng : - 122.400742086205 , altitude : 0 , }, range : 2400 , tilt : 65 , heading : 0 , mode : 'ROADMAP' , internalUsageAttributionIds : [ 'gmp_git_jsapisamples_v1_3d-rendering' ], }); document . body . append ( map ); // Create the controls container const controls = document . createElement ( 'div' ); controls . id = 'controls' ; controls . classList . add ( 'map-mode-control' ); // Create the select element const selector = document . createElement ( 'select' ); selector . id = 'map-mode' ; const modes = [ 'ROADMAP' , 'SATELLITE' , 'HYBRID' ]; modes . forEach (( modeName ) = > { const option = document . createElement ( 'option' ); option . value = modeName ; option . textContent = modeName ; if ( modeName === 'ROADMAP' ) { option . selected = true ; } selector . appendChild ( option ); }); selector . addEventListener ( 'change' , ( event ) = > { map . mode = event . target . value ; }); controls . appendChild ( selector ); document . body . appendChild ( controls ); } init ();
CSS
html , body { height : 100 % ; margin : 0 ; padding : 0 ; font-family : 'Roboto' , 'Helvetica' , 'Arial' , sans-serif ; } gmp-map-3d { height : 100 % ; width : 100 % ; } . map-mode-control { position : fixed ; bottom : 24 px ; right : 75 px ; display : flex ; align-items : center ; background-color : rgba ( 255 , 255 , 255 , 0.9 ); padding : 8 px ; border-radius : 8 px ; box-shadow : 0 4 px 20 px rgba ( 0 , 0 , 0 , 0.15 ); backdrop-filter : blur ( 8 px ); z-index : 1 ; } . map-mode-control select { font-size : 13 px ; padding : 4 px 8 px ; border : 1 px solid #dadce0 ; border-radius : 6 px ; background-color : white ; color : #3c4043 ; cursor : pointer ; outline : none ; transition : border-color 0.2 s , box-shadow 0.2 s ; } . map-mode-control select : hover { border-color : #1a73e8 ; } . map-mode-control select : focus { border-color : #1a73e8 ; box-shadow : 0 0 0 2 px rgba ( 26 , 115 , 232 , 0.2 ); }
HTML
<html> <head> <title>3d-map-roadmap</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> <!-- 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: "alpha" });</script> </head> <body> </body> </html>
Try Sample
Key benefits
- Globe: you can now provide a full map experience for various use cases leveraging abstract and photorealistic map imagery.
- Customization: You can now switch between modes with a custom button or function without reloading the overall component.

