diff --git a/dist/index.html b/dist/index.html
index 02b817c0f..dd5dacffd 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -10,6 +10,7 @@
Maps JSAPI Samples
3d-accessibility-features
3d-camera-boundary
3d-camera-center
+ 3d-camera-position
3d-camera-to-around
3d-clamp-mode
3d-coverage-map
diff --git a/dist/samples/3d-camera-position/app/.eslintsrc.json b/dist/samples/3d-camera-position/app/.eslintsrc.json
new file mode 100644
index 000000000..4c44dab04
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/.eslintsrc.json
@@ -0,0 +1,13 @@
+{
+ "extends": [
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "rules": {
+ "@typescript-eslint/ban-ts-comment": 0,
+ "@typescript-eslint/no-this-alias": 1,
+ "@typescript-eslint/no-empty-function": 1,
+ "@typescript-eslint/explicit-module-boundary-types": 1,
+ "@typescript-eslint/no-unused-vars": 1
+ }
+}
diff --git a/dist/samples/3d-camera-position/app/README.md b/dist/samples/3d-camera-position/app/README.md
new file mode 100644
index 000000000..7ff252ae8
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/README.md
@@ -0,0 +1,48 @@
+# Google Maps JavaScript Sample
+
+## 3d-camera-position
+
+An interactive playground designed to help developers understand and experiment with camera positioning in Google Maps 3D.
+
+## Features
+
+- **Live Camera Controls**: Real-time sliders for adjusting `heading`, `tilt`, `range`, and `fov` properties.
+- **Coordinate Mapping**: Direct controls to set the camera's focal point via `Latitude`, `Longitude`, and `Altitude`.
+- **Code Generator**: Dynamically generates the resulting `` HTML tag with mapped properties for easy copying and pasting.
+- **Continuous Event Syncing**: Listens to map interaction events (like dragging and panning) to keep UI readouts strictly synchronized with live map state.
+
+## Setup
+
+### Before starting run:
+
+`npm i`
+
+### Run an example on a local web server
+
+`cd samples/3d-camera-position`
+`npm start`
+
+### Build an individual example
+
+`cd samples/3d-camera-position`
+`npm run build`
+
+From 'samples':
+
+`npm run build --workspace=3d-camera-position/`
+
+### Build all of the examples.
+
+From 'samples':
+
+`npm run build-all`
+
+### Run lint to check for problems
+
+`cd samples/3d-camera-position`
+`npx eslint index.ts`
+
+## Feedback
+
+For feedback related to this sample, please open a new issue on
+[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues).
diff --git a/dist/samples/3d-camera-position/app/index.html b/dist/samples/3d-camera-position/app/index.html
new file mode 100644
index 000000000..2d083ed10
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/index.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+ `
+ Google Maps 3D - Camera Position Controller
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/samples/3d-camera-position/app/index.ts b/dist/samples/3d-camera-position/app/index.ts
new file mode 100644
index 000000000..fc84e3e24
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/index.ts
@@ -0,0 +1,147 @@
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+// [START maps_3d_camera_position]
+async function initMap(): Promise {
+ // Declare the needed libraries.
+ await google.maps.importLibrary('maps3d');
+
+ const map3DElement = document.querySelector('gmp-map-3d')!;
+
+ // Elements from HTML
+ const headingSlider = document.getElementById(
+ 'heading'
+ ) as HTMLInputElement;
+ const tiltSlider = document.getElementById('tilt') as HTMLInputElement;
+ const rangeSlider = document.getElementById('range') as HTMLInputElement;
+ const latSlider = document.getElementById('lat') as HTMLInputElement;
+ const lngSlider = document.getElementById('lng') as HTMLInputElement;
+ const fovSlider = document.getElementById('fov') as HTMLInputElement;
+ const rollSlider = document.getElementById('roll') as HTMLInputElement;
+
+ const headingVal = document.getElementById('heading-val') as HTMLElement;
+ const tiltVal = document.getElementById('tilt-val') as HTMLElement;
+ const rangeVal = document.getElementById('range-val') as HTMLElement;
+ const altitudeVal = document.getElementById('altitude-val') as HTMLElement;
+ const fovVal = document.getElementById('fov-val') as HTMLElement;
+ const rollVal = document.getElementById('roll-val') as HTMLElement;
+ const codeElem = document.getElementById('generated-code') as HTMLElement;
+ const copyBtn = document.getElementById('copy-btn') as HTMLButtonElement;
+
+ let currentAltitude = 30;
+ let isUserInteracting = false;
+
+ // Update values on UI when the map changes.
+ const updateUI = () => {
+ const heading = map3DElement.heading?.toFixed(0) ?? '0';
+ const tilt = map3DElement.tilt?.toFixed(0) ?? '0';
+ const range = map3DElement.range?.toFixed(0) ?? '0';
+ const rawFov = parseFloat(map3DElement.fov?.toFixed(0) ?? '45');
+ const fovClamped = Math.min(80, Math.max(5, rawFov));
+ const fov = fovClamped.toString();
+ const roll = map3DElement.roll?.toFixed(0) ?? '0';
+ const center = map3DElement.center;
+ const mode = map3DElement.mode;
+
+ headingVal.textContent = heading;
+ tiltVal.textContent = tilt;
+ rangeVal.textContent = range;
+ fovVal.textContent = fov;
+ rollVal.textContent = roll;
+
+ if (!isUserInteracting) {
+ fovSlider.value = fov;
+ headingSlider.value = heading;
+ tiltSlider.value = tilt;
+ rangeSlider.value = Math.min(10000, parseFloat(range)).toString();
+ rollSlider.value = roll;
+ }
+
+ if (center) {
+ const lat = center.lat.toFixed(4);
+ const lng = center.lng.toFixed(4);
+ const alt = currentAltitude.toFixed(0);
+
+ latSlider.value = lat;
+ lngSlider.value = lng;
+ altitudeVal.textContent = alt;
+
+ codeElem.textContent = ` `;
+ }
+ };
+
+ // Copy generated HTML to clipboard.
+ copyBtn.addEventListener('click', () => {
+ void navigator.clipboard.writeText(codeElem.textContent || '');
+ copyBtn.textContent = 'Copied!';
+ setTimeout(() => {
+ copyBtn.textContent = 'Copy HTML';
+ }, 2000);
+ });
+
+ // Listen to slider changes using event delegation.
+ const panel = document.querySelector('.panel') as HTMLElement;
+
+ panel.addEventListener('input', (e) => {
+ const target = e.target as HTMLInputElement;
+ if (target.tagName !== 'INPUT') return;
+
+ isUserInteracting = true;
+ const prop = target.name;
+ const val = parseFloat(target.value);
+
+ if (prop === 'lat') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: val,
+ lng: currentCenter.lng,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'lng') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: val,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'altitude') {
+ currentAltitude = val;
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: currentCenter.lng,
+ altitude: val,
+ };
+ }
+ } else {
+ map3DElement[prop] = val;
+ }
+ updateUI();
+ });
+
+ panel.addEventListener('change', (e) => {
+ const target = e.target as HTMLInputElement;
+ if (target.tagName === 'INPUT') {
+ isUserInteracting = false;
+ }
+ });
+
+ // Update UI on camera change events.
+ map3DElement.addEventListener('gmp-headingchange', updateUI);
+ map3DElement.addEventListener('gmp-tiltchange', updateUI);
+ map3DElement.addEventListener('gmp-rangechange', updateUI);
+ map3DElement.addEventListener('gmp-fovchange', updateUI);
+
+ // Initial UI sync
+ setTimeout(updateUI, 500);
+}
+
+void initMap();
+// [END maps_3d_camera_position]
diff --git a/dist/samples/3d-camera-position/app/package.json b/dist/samples/3d-camera-position/app/package.json
new file mode 100644
index 000000000..94e7c0c98
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@js-api-samples/3d-camera-position",
+ "version": "1.0.0",
+ "scripts": {
+ "build": "tsc && bash ../jsfiddle.sh 3d-camera-position && bash ../app.sh 3d-camera-position && bash ../docs.sh 3d-camera-position && npm run build:vite --workspace=. && bash ../dist.sh 3d-camera-position",
+ "test": "tsc && npm run build:vite --workspace=.",
+ "start": "tsc && vite build --base './' && vite",
+ "build:vite": "vite build --base './'",
+ "preview": "vite preview"
+ },
+ "dependencies": {}
+}
diff --git a/dist/samples/3d-camera-position/app/style.css b/dist/samples/3d-camera-position/app/style.css
new file mode 100644
index 000000000..bf6fbbcfe
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/style.css
@@ -0,0 +1,215 @@
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+/* [START maps_3d_camera_position] */
+
+html,
+body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ font-family:
+ 'Inter',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Oxygen,
+ Ubuntu,
+ Cantarell,
+ 'Open Sans',
+ 'Helvetica Neue',
+ sans-serif;
+ background-color: #0f172a;
+ color: #e2e8f0;
+}
+
+gmp-map-3d {
+ height: 100%;
+ width: 100%;
+}
+
+/* Glassmorphism UI Overlay */
+#ui-container {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ width: 320px;
+ z-index: 10;
+}
+
+.panel {
+ background: rgba(15, 23, 42, 0.75);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 16px;
+ padding: 24px;
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
+}
+
+h1 {
+ font-size: 1.25rem;
+ font-weight: 700;
+ margin: 0 0 4px 0;
+ background: linear-gradient(to right, #38bdf8, #818cf8);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.sub-title {
+ font-size: 0.85rem;
+ color: #94a3b8;
+ margin: 0 0 20px 0;
+}
+
+h2 {
+ font-size: 0.95rem;
+ font-weight: 600;
+ margin: 16px 0 8px 0;
+ color: #f8fafc;
+}
+
+.control-group {
+ margin-bottom: 16px;
+}
+
+label {
+ display: block;
+ font-size: 0.85rem;
+ margin-bottom: 6px;
+ color: #cbd5e1;
+}
+
+span {
+ font-weight: 600;
+ color: #38bdf8;
+}
+
+.row {
+ display: flex;
+ gap: 12px;
+}
+
+.col {
+ flex: 1;
+}
+
+input[type='number'] {
+ font-family: 'Fira Code', monospace;
+ background: rgba(15, 23, 42, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ color: #f8fafc;
+ padding: 4px 8px;
+ border-radius: 6px;
+ outline: none;
+}
+
+input[type='range'] {
+ width: 100%;
+ height: 4px;
+ background: #334155;
+ border-radius: 2px;
+ outline: none;
+ -webkit-appearance: none;
+}
+
+input[type='range']::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: #38bdf8;
+ cursor: pointer;
+ box-shadow: 0 0 8px rgba(56, 189, 248, 0.5);
+ transition: all 0.2s ease;
+}
+
+input[type='range']::-webkit-slider-thumb:hover {
+ transform: scale(1.2);
+ background: #60a5fa;
+}
+
+.buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+button {
+ background: rgba(51, 65, 85, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ color: #f8fafc;
+ padding: 10px 16px;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 0.85rem;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ text-align: left;
+}
+
+button:hover {
+ background: rgba(56, 189, 248, 0.2);
+ border-color: rgba(56, 189, 248, 0.4);
+ transform: translateY(-1px);
+}
+
+button:active {
+ transform: translateY(0);
+}
+
+.status-group p {
+ font-size: 0.8rem;
+ color: #94a3b8;
+ margin: 4px 0;
+ background: rgba(30, 41, 59, 0.5);
+ padding: 6px 10px;
+ border-radius: 6px;
+ font-family: monospace;
+}
+
+.code-box {
+ position: relative;
+ background: rgba(15, 23, 42, 0.9);
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ margin-top: 8px;
+}
+
+pre {
+ margin: 0;
+ padding: 12px;
+ overflow-x: auto;
+}
+
+code {
+ font-family: 'Fira Code', monospace;
+ font-size: 0.75rem;
+ color: #38bdf8;
+}
+
+#copy-btn {
+ display: block;
+ width: 100%;
+ margin-top: 8px;
+ padding: 8px;
+ font-size: 0.85rem;
+ font-weight: 600;
+ background: #334155;
+ color: #f8fafc;
+ border: none;
+ border-radius: 6px;
+ text-align: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#copy-btn:hover {
+ background: #38bdf8;
+ color: #0f172a;
+}
+
+/* [END maps_3d_camera_position] */
diff --git a/dist/samples/3d-camera-position/app/tsconfig.json b/dist/samples/3d-camera-position/app/tsconfig.json
new file mode 100644
index 000000000..976bcc6ef
--- /dev/null
+++ b/dist/samples/3d-camera-position/app/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "rootDir": "."
+ },
+ "include": ["./*.ts"]
+}
diff --git a/dist/samples/3d-camera-position/dist/assets/index-FbE_-4e_.css b/dist/samples/3d-camera-position/dist/assets/index-FbE_-4e_.css
new file mode 100644
index 000000000..fa2e9e337
--- /dev/null
+++ b/dist/samples/3d-camera-position/dist/assets/index-FbE_-4e_.css
@@ -0,0 +1 @@
+html,body{color:#e2e8f0;background-color:#0f172a;height:100%;margin:0;padding:0;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif}gmp-map-3d{width:100%;height:100%}#ui-container{z-index:10;width:320px;position:absolute;top:20px;left:20px}.panel{-webkit-backdrop-filter:blur(12px);background:#0f172abf;border:1px solid #ffffff1a;border-radius:16px;padding:24px;box-shadow:0 8px 32px #0000005e}h1{background:linear-gradient(90deg,#38bdf8,#818cf8);-webkit-text-fill-color:transparent;-webkit-background-clip:text;margin:0 0 4px;font-size:1.25rem;font-weight:700}.sub-title{color:#94a3b8;margin:0 0 20px;font-size:.85rem}h2{color:#f8fafc;margin:16px 0 8px;font-size:.95rem;font-weight:600}.control-group{margin-bottom:16px}label{color:#cbd5e1;margin-bottom:6px;font-size:.85rem;display:block}span{color:#38bdf8;font-weight:600}.row{gap:12px;display:flex}.col{flex:1}input[type=number]{color:#f8fafc;background:#0f172a80;border:1px solid #ffffff1a;border-radius:6px;outline:none;padding:4px 8px;font-family:Fira Code,monospace}input[type=range]{-webkit-appearance:none;background:#334155;border-radius:2px;outline:none;width:100%;height:4px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#38bdf8;border-radius:50%;width:16px;height:16px;transition:all .2s;box-shadow:0 0 8px #38bdf880}input[type=range]::-webkit-slider-thumb:hover{background:#60a5fa;transform:scale(1.2)}.buttons{flex-direction:column;gap:8px;display:flex}button{color:#f8fafc;cursor:pointer;text-align:left;background:#33415580;border:1px solid #ffffff0d;border-radius:8px;padding:10px 16px;font-size:.85rem;font-weight:500;transition:all .2s}button:hover{background:#38bdf833;border-color:#38bdf866;transform:translateY(-1px)}button:active{transform:translateY(0)}.status-group p{color:#94a3b8;background:#1e293b80;border-radius:6px;margin:4px 0;padding:6px 10px;font-family:monospace;font-size:.8rem}.code-box{background:#0f172ae6;border:1px solid #ffffff0d;border-radius:8px;margin-top:8px;position:relative}pre{margin:0;padding:12px;overflow-x:auto}code{color:#38bdf8;font-family:Fira Code,monospace;font-size:.75rem}#copy-btn{color:#f8fafc;text-align:center;cursor:pointer;background:#334155;border:none;border-radius:6px;width:100%;margin-top:8px;padding:8px;font-size:.85rem;font-weight:600;transition:all .2s;display:block}#copy-btn:hover{color:#0f172a;background:#38bdf8}
diff --git a/dist/samples/3d-camera-position/dist/assets/index-HwMXX0CU.js b/dist/samples/3d-camera-position/dist/assets/index-HwMXX0CU.js
new file mode 100644
index 000000000..142ebc72d
--- /dev/null
+++ b/dist/samples/3d-camera-position/dist/assets/index-HwMXX0CU.js
@@ -0,0 +1 @@
+(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();async function e(){await google.maps.importLibrary(`maps3d`);let e=document.querySelector(`gmp-map-3d`),t=document.getElementById(`heading`),n=document.getElementById(`tilt`),r=document.getElementById(`range`),i=document.getElementById(`lat`),a=document.getElementById(`lng`),o=document.getElementById(`fov`),s=document.getElementById(`roll`),c=document.getElementById(`heading-val`),l=document.getElementById(`tilt-val`),u=document.getElementById(`range-val`),d=document.getElementById(`altitude-val`),f=document.getElementById(`fov-val`),p=document.getElementById(`roll-val`),m=document.getElementById(`generated-code`),h=document.getElementById(`copy-btn`),g=30,_=!1,v=()=>{let h=e.heading?.toFixed(0)??`0`,v=e.tilt?.toFixed(0)??`0`,y=e.range?.toFixed(0)??`0`,b=parseFloat(e.fov?.toFixed(0)??`45`),x=Math.min(80,Math.max(5,b)).toString(),S=e.roll?.toFixed(0)??`0`,C=e.center,w=e.mode;if(c.textContent=h,l.textContent=v,u.textContent=y,f.textContent=x,p.textContent=S,_||(o.value=x,t.value=h,n.value=v,r.value=Math.min(1e4,parseFloat(y)).toString(),s.value=S),C){let e=C.lat.toFixed(4),t=C.lng.toFixed(4),n=g.toFixed(0);i.value=e,a.value=t,d.textContent=n,m.textContent=` `}};h.addEventListener(`click`,()=>{navigator.clipboard.writeText(m.textContent||``),h.textContent=`Copied!`,setTimeout(()=>{h.textContent=`Copy HTML`},2e3)});let y=document.querySelector(`.panel`);y.addEventListener(`input`,t=>{let n=t.target;if(n.tagName!==`INPUT`)return;_=!0;let r=n.name,i=parseFloat(n.value);if(r===`lat`){let t=e.center;t&&(e.center={lat:i,lng:t.lng,altitude:t.altitude})}else if(r===`lng`){let t=e.center;t&&(e.center={lat:t.lat,lng:i,altitude:t.altitude})}else if(r===`altitude`){g=i;let t=e.center;t&&(e.center={lat:t.lat,lng:t.lng,altitude:i})}else e[r]=i;v()}),y.addEventListener(`change`,e=>{e.target.tagName===`INPUT`&&(_=!1)}),e.addEventListener(`gmp-headingchange`,v),e.addEventListener(`gmp-tiltchange`,v),e.addEventListener(`gmp-rangechange`,v),e.addEventListener(`gmp-fovchange`,v),setTimeout(v,500)}e();
\ No newline at end of file
diff --git a/dist/samples/3d-camera-position/dist/index.html b/dist/samples/3d-camera-position/dist/index.html
new file mode 100644
index 000000000..5f45e6a0a
--- /dev/null
+++ b/dist/samples/3d-camera-position/dist/index.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+ `
+ Google Maps 3D - Camera Position Controller
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/samples/3d-camera-position/docs/index.html b/dist/samples/3d-camera-position/docs/index.html
new file mode 100644
index 000000000..2d083ed10
--- /dev/null
+++ b/dist/samples/3d-camera-position/docs/index.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+ `
+ Google Maps 3D - Camera Position Controller
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/samples/3d-camera-position/docs/index.js b/dist/samples/3d-camera-position/docs/index.js
new file mode 100644
index 000000000..a7b9edfe7
--- /dev/null
+++ b/dist/samples/3d-camera-position/docs/index.js
@@ -0,0 +1,131 @@
+"use strict";
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+// [START maps_3d_camera_position]
+async function initMap() {
+ // Declare the needed libraries.
+ await google.maps.importLibrary('maps3d');
+ const map3DElement = document.querySelector('gmp-map-3d');
+ // Elements from HTML
+ const headingSlider = document.getElementById('heading');
+ const tiltSlider = document.getElementById('tilt');
+ const rangeSlider = document.getElementById('range');
+ const latSlider = document.getElementById('lat');
+ const lngSlider = document.getElementById('lng');
+ const fovSlider = document.getElementById('fov');
+ const rollSlider = document.getElementById('roll');
+ const headingVal = document.getElementById('heading-val');
+ const tiltVal = document.getElementById('tilt-val');
+ const rangeVal = document.getElementById('range-val');
+ const altitudeVal = document.getElementById('altitude-val');
+ const fovVal = document.getElementById('fov-val');
+ const rollVal = document.getElementById('roll-val');
+ const codeElem = document.getElementById('generated-code');
+ const copyBtn = document.getElementById('copy-btn');
+ let currentAltitude = 30;
+ let isUserInteracting = false;
+ // Update values on UI when the map changes.
+ const updateUI = () => {
+ const heading = map3DElement.heading?.toFixed(0) ?? '0';
+ const tilt = map3DElement.tilt?.toFixed(0) ?? '0';
+ const range = map3DElement.range?.toFixed(0) ?? '0';
+ const rawFov = parseFloat(map3DElement.fov?.toFixed(0) ?? '45');
+ const fovClamped = Math.min(80, Math.max(5, rawFov));
+ const fov = fovClamped.toString();
+ const roll = map3DElement.roll?.toFixed(0) ?? '0';
+ const center = map3DElement.center;
+ const mode = map3DElement.mode;
+ headingVal.textContent = heading;
+ tiltVal.textContent = tilt;
+ rangeVal.textContent = range;
+ fovVal.textContent = fov;
+ rollVal.textContent = roll;
+ if (!isUserInteracting) {
+ fovSlider.value = fov;
+ headingSlider.value = heading;
+ tiltSlider.value = tilt;
+ rangeSlider.value = Math.min(10000, parseFloat(range)).toString();
+ rollSlider.value = roll;
+ }
+ if (center) {
+ const lat = center.lat.toFixed(4);
+ const lng = center.lng.toFixed(4);
+ const alt = currentAltitude.toFixed(0);
+ latSlider.value = lat;
+ lngSlider.value = lng;
+ altitudeVal.textContent = alt;
+ codeElem.textContent = ` `;
+ }
+ };
+ // Copy generated HTML to clipboard.
+ copyBtn.addEventListener('click', () => {
+ void navigator.clipboard.writeText(codeElem.textContent || '');
+ copyBtn.textContent = 'Copied!';
+ setTimeout(() => {
+ copyBtn.textContent = 'Copy HTML';
+ }, 2000);
+ });
+ // Listen to slider changes using event delegation.
+ const panel = document.querySelector('.panel');
+ panel.addEventListener('input', (e) => {
+ const target = e.target;
+ if (target.tagName !== 'INPUT')
+ return;
+ isUserInteracting = true;
+ const prop = target.name;
+ const val = parseFloat(target.value);
+ if (prop === 'lat') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: val,
+ lng: currentCenter.lng,
+ altitude: currentCenter.altitude,
+ };
+ }
+ }
+ else if (prop === 'lng') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: val,
+ altitude: currentCenter.altitude,
+ };
+ }
+ }
+ else if (prop === 'altitude') {
+ currentAltitude = val;
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: currentCenter.lng,
+ altitude: val,
+ };
+ }
+ }
+ else {
+ map3DElement[prop] = val;
+ }
+ updateUI();
+ });
+ panel.addEventListener('change', (e) => {
+ const target = e.target;
+ if (target.tagName === 'INPUT') {
+ isUserInteracting = false;
+ }
+ });
+ // Update UI on camera change events.
+ map3DElement.addEventListener('gmp-headingchange', updateUI);
+ map3DElement.addEventListener('gmp-tiltchange', updateUI);
+ map3DElement.addEventListener('gmp-rangechange', updateUI);
+ map3DElement.addEventListener('gmp-fovchange', updateUI);
+ // Initial UI sync
+ setTimeout(updateUI, 500);
+}
+void initMap();
+// [END maps_3d_camera_position]
diff --git a/dist/samples/3d-camera-position/docs/index.ts b/dist/samples/3d-camera-position/docs/index.ts
new file mode 100644
index 000000000..fc84e3e24
--- /dev/null
+++ b/dist/samples/3d-camera-position/docs/index.ts
@@ -0,0 +1,147 @@
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+// [START maps_3d_camera_position]
+async function initMap(): Promise {
+ // Declare the needed libraries.
+ await google.maps.importLibrary('maps3d');
+
+ const map3DElement = document.querySelector('gmp-map-3d')!;
+
+ // Elements from HTML
+ const headingSlider = document.getElementById(
+ 'heading'
+ ) as HTMLInputElement;
+ const tiltSlider = document.getElementById('tilt') as HTMLInputElement;
+ const rangeSlider = document.getElementById('range') as HTMLInputElement;
+ const latSlider = document.getElementById('lat') as HTMLInputElement;
+ const lngSlider = document.getElementById('lng') as HTMLInputElement;
+ const fovSlider = document.getElementById('fov') as HTMLInputElement;
+ const rollSlider = document.getElementById('roll') as HTMLInputElement;
+
+ const headingVal = document.getElementById('heading-val') as HTMLElement;
+ const tiltVal = document.getElementById('tilt-val') as HTMLElement;
+ const rangeVal = document.getElementById('range-val') as HTMLElement;
+ const altitudeVal = document.getElementById('altitude-val') as HTMLElement;
+ const fovVal = document.getElementById('fov-val') as HTMLElement;
+ const rollVal = document.getElementById('roll-val') as HTMLElement;
+ const codeElem = document.getElementById('generated-code') as HTMLElement;
+ const copyBtn = document.getElementById('copy-btn') as HTMLButtonElement;
+
+ let currentAltitude = 30;
+ let isUserInteracting = false;
+
+ // Update values on UI when the map changes.
+ const updateUI = () => {
+ const heading = map3DElement.heading?.toFixed(0) ?? '0';
+ const tilt = map3DElement.tilt?.toFixed(0) ?? '0';
+ const range = map3DElement.range?.toFixed(0) ?? '0';
+ const rawFov = parseFloat(map3DElement.fov?.toFixed(0) ?? '45');
+ const fovClamped = Math.min(80, Math.max(5, rawFov));
+ const fov = fovClamped.toString();
+ const roll = map3DElement.roll?.toFixed(0) ?? '0';
+ const center = map3DElement.center;
+ const mode = map3DElement.mode;
+
+ headingVal.textContent = heading;
+ tiltVal.textContent = tilt;
+ rangeVal.textContent = range;
+ fovVal.textContent = fov;
+ rollVal.textContent = roll;
+
+ if (!isUserInteracting) {
+ fovSlider.value = fov;
+ headingSlider.value = heading;
+ tiltSlider.value = tilt;
+ rangeSlider.value = Math.min(10000, parseFloat(range)).toString();
+ rollSlider.value = roll;
+ }
+
+ if (center) {
+ const lat = center.lat.toFixed(4);
+ const lng = center.lng.toFixed(4);
+ const alt = currentAltitude.toFixed(0);
+
+ latSlider.value = lat;
+ lngSlider.value = lng;
+ altitudeVal.textContent = alt;
+
+ codeElem.textContent = ` `;
+ }
+ };
+
+ // Copy generated HTML to clipboard.
+ copyBtn.addEventListener('click', () => {
+ void navigator.clipboard.writeText(codeElem.textContent || '');
+ copyBtn.textContent = 'Copied!';
+ setTimeout(() => {
+ copyBtn.textContent = 'Copy HTML';
+ }, 2000);
+ });
+
+ // Listen to slider changes using event delegation.
+ const panel = document.querySelector('.panel') as HTMLElement;
+
+ panel.addEventListener('input', (e) => {
+ const target = e.target as HTMLInputElement;
+ if (target.tagName !== 'INPUT') return;
+
+ isUserInteracting = true;
+ const prop = target.name;
+ const val = parseFloat(target.value);
+
+ if (prop === 'lat') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: val,
+ lng: currentCenter.lng,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'lng') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: val,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'altitude') {
+ currentAltitude = val;
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: currentCenter.lng,
+ altitude: val,
+ };
+ }
+ } else {
+ map3DElement[prop] = val;
+ }
+ updateUI();
+ });
+
+ panel.addEventListener('change', (e) => {
+ const target = e.target as HTMLInputElement;
+ if (target.tagName === 'INPUT') {
+ isUserInteracting = false;
+ }
+ });
+
+ // Update UI on camera change events.
+ map3DElement.addEventListener('gmp-headingchange', updateUI);
+ map3DElement.addEventListener('gmp-tiltchange', updateUI);
+ map3DElement.addEventListener('gmp-rangechange', updateUI);
+ map3DElement.addEventListener('gmp-fovchange', updateUI);
+
+ // Initial UI sync
+ setTimeout(updateUI, 500);
+}
+
+void initMap();
+// [END maps_3d_camera_position]
diff --git a/dist/samples/3d-camera-position/docs/style.css b/dist/samples/3d-camera-position/docs/style.css
new file mode 100644
index 000000000..bf6fbbcfe
--- /dev/null
+++ b/dist/samples/3d-camera-position/docs/style.css
@@ -0,0 +1,215 @@
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+/* [START maps_3d_camera_position] */
+
+html,
+body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ font-family:
+ 'Inter',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Oxygen,
+ Ubuntu,
+ Cantarell,
+ 'Open Sans',
+ 'Helvetica Neue',
+ sans-serif;
+ background-color: #0f172a;
+ color: #e2e8f0;
+}
+
+gmp-map-3d {
+ height: 100%;
+ width: 100%;
+}
+
+/* Glassmorphism UI Overlay */
+#ui-container {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ width: 320px;
+ z-index: 10;
+}
+
+.panel {
+ background: rgba(15, 23, 42, 0.75);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 16px;
+ padding: 24px;
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
+}
+
+h1 {
+ font-size: 1.25rem;
+ font-weight: 700;
+ margin: 0 0 4px 0;
+ background: linear-gradient(to right, #38bdf8, #818cf8);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.sub-title {
+ font-size: 0.85rem;
+ color: #94a3b8;
+ margin: 0 0 20px 0;
+}
+
+h2 {
+ font-size: 0.95rem;
+ font-weight: 600;
+ margin: 16px 0 8px 0;
+ color: #f8fafc;
+}
+
+.control-group {
+ margin-bottom: 16px;
+}
+
+label {
+ display: block;
+ font-size: 0.85rem;
+ margin-bottom: 6px;
+ color: #cbd5e1;
+}
+
+span {
+ font-weight: 600;
+ color: #38bdf8;
+}
+
+.row {
+ display: flex;
+ gap: 12px;
+}
+
+.col {
+ flex: 1;
+}
+
+input[type='number'] {
+ font-family: 'Fira Code', monospace;
+ background: rgba(15, 23, 42, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ color: #f8fafc;
+ padding: 4px 8px;
+ border-radius: 6px;
+ outline: none;
+}
+
+input[type='range'] {
+ width: 100%;
+ height: 4px;
+ background: #334155;
+ border-radius: 2px;
+ outline: none;
+ -webkit-appearance: none;
+}
+
+input[type='range']::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: #38bdf8;
+ cursor: pointer;
+ box-shadow: 0 0 8px rgba(56, 189, 248, 0.5);
+ transition: all 0.2s ease;
+}
+
+input[type='range']::-webkit-slider-thumb:hover {
+ transform: scale(1.2);
+ background: #60a5fa;
+}
+
+.buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+button {
+ background: rgba(51, 65, 85, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ color: #f8fafc;
+ padding: 10px 16px;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 0.85rem;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ text-align: left;
+}
+
+button:hover {
+ background: rgba(56, 189, 248, 0.2);
+ border-color: rgba(56, 189, 248, 0.4);
+ transform: translateY(-1px);
+}
+
+button:active {
+ transform: translateY(0);
+}
+
+.status-group p {
+ font-size: 0.8rem;
+ color: #94a3b8;
+ margin: 4px 0;
+ background: rgba(30, 41, 59, 0.5);
+ padding: 6px 10px;
+ border-radius: 6px;
+ font-family: monospace;
+}
+
+.code-box {
+ position: relative;
+ background: rgba(15, 23, 42, 0.9);
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ margin-top: 8px;
+}
+
+pre {
+ margin: 0;
+ padding: 12px;
+ overflow-x: auto;
+}
+
+code {
+ font-family: 'Fira Code', monospace;
+ font-size: 0.75rem;
+ color: #38bdf8;
+}
+
+#copy-btn {
+ display: block;
+ width: 100%;
+ margin-top: 8px;
+ padding: 8px;
+ font-size: 0.85rem;
+ font-weight: 600;
+ background: #334155;
+ color: #f8fafc;
+ border: none;
+ border-radius: 6px;
+ text-align: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#copy-btn:hover {
+ background: #38bdf8;
+ color: #0f172a;
+}
+
+/* [END maps_3d_camera_position] */
diff --git a/dist/samples/3d-camera-position/jsfiddle/demo.css b/dist/samples/3d-camera-position/jsfiddle/demo.css
new file mode 100644
index 000000000..d2bf395dc
--- /dev/null
+++ b/dist/samples/3d-camera-position/jsfiddle/demo.css
@@ -0,0 +1,212 @@
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+html,
+body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ font-family:
+ 'Inter',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Oxygen,
+ Ubuntu,
+ Cantarell,
+ 'Open Sans',
+ 'Helvetica Neue',
+ sans-serif;
+ background-color: #0f172a;
+ color: #e2e8f0;
+}
+
+gmp-map-3d {
+ height: 100%;
+ width: 100%;
+}
+
+/* Glassmorphism UI Overlay */
+#ui-container {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ width: 320px;
+ z-index: 10;
+}
+
+.panel {
+ background: rgba(15, 23, 42, 0.75);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 16px;
+ padding: 24px;
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
+}
+
+h1 {
+ font-size: 1.25rem;
+ font-weight: 700;
+ margin: 0 0 4px 0;
+ background: linear-gradient(to right, #38bdf8, #818cf8);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.sub-title {
+ font-size: 0.85rem;
+ color: #94a3b8;
+ margin: 0 0 20px 0;
+}
+
+h2 {
+ font-size: 0.95rem;
+ font-weight: 600;
+ margin: 16px 0 8px 0;
+ color: #f8fafc;
+}
+
+.control-group {
+ margin-bottom: 16px;
+}
+
+label {
+ display: block;
+ font-size: 0.85rem;
+ margin-bottom: 6px;
+ color: #cbd5e1;
+}
+
+span {
+ font-weight: 600;
+ color: #38bdf8;
+}
+
+.row {
+ display: flex;
+ gap: 12px;
+}
+
+.col {
+ flex: 1;
+}
+
+input[type='number'] {
+ font-family: 'Fira Code', monospace;
+ background: rgba(15, 23, 42, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ color: #f8fafc;
+ padding: 4px 8px;
+ border-radius: 6px;
+ outline: none;
+}
+
+input[type='range'] {
+ width: 100%;
+ height: 4px;
+ background: #334155;
+ border-radius: 2px;
+ outline: none;
+ -webkit-appearance: none;
+}
+
+input[type='range']::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: #38bdf8;
+ cursor: pointer;
+ box-shadow: 0 0 8px rgba(56, 189, 248, 0.5);
+ transition: all 0.2s ease;
+}
+
+input[type='range']::-webkit-slider-thumb:hover {
+ transform: scale(1.2);
+ background: #60a5fa;
+}
+
+.buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+button {
+ background: rgba(51, 65, 85, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ color: #f8fafc;
+ padding: 10px 16px;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 0.85rem;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ text-align: left;
+}
+
+button:hover {
+ background: rgba(56, 189, 248, 0.2);
+ border-color: rgba(56, 189, 248, 0.4);
+ transform: translateY(-1px);
+}
+
+button:active {
+ transform: translateY(0);
+}
+
+.status-group p {
+ font-size: 0.8rem;
+ color: #94a3b8;
+ margin: 4px 0;
+ background: rgba(30, 41, 59, 0.5);
+ padding: 6px 10px;
+ border-radius: 6px;
+ font-family: monospace;
+}
+
+.code-box {
+ position: relative;
+ background: rgba(15, 23, 42, 0.9);
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ margin-top: 8px;
+}
+
+pre {
+ margin: 0;
+ padding: 12px;
+ overflow-x: auto;
+}
+
+code {
+ font-family: 'Fira Code', monospace;
+ font-size: 0.75rem;
+ color: #38bdf8;
+}
+
+#copy-btn {
+ display: block;
+ width: 100%;
+ margin-top: 8px;
+ padding: 8px;
+ font-size: 0.85rem;
+ font-weight: 600;
+ background: #334155;
+ color: #f8fafc;
+ border: none;
+ border-radius: 6px;
+ text-align: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#copy-btn:hover {
+ background: #38bdf8;
+ color: #0f172a;
+}
diff --git a/dist/samples/3d-camera-position/jsfiddle/demo.details b/dist/samples/3d-camera-position/jsfiddle/demo.details
new file mode 100644
index 000000000..46e2ba897
--- /dev/null
+++ b/dist/samples/3d-camera-position/jsfiddle/demo.details
@@ -0,0 +1,7 @@
+name: 3d-camera-position
+authors:
+ - Geo Developer IX Documentation Team
+tags:
+ - google maps
+load_type: h
+description: Sample code supporting Google Maps Platform JavaScript API documentation.
diff --git a/dist/samples/3d-camera-position/jsfiddle/demo.html b/dist/samples/3d-camera-position/jsfiddle/demo.html
new file mode 100644
index 000000000..123faa0fb
--- /dev/null
+++ b/dist/samples/3d-camera-position/jsfiddle/demo.html
@@ -0,0 +1,146 @@
+
+
+
+
+
+ `
+ Google Maps 3D - Camera Position Controller
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/samples/3d-camera-position/jsfiddle/demo.js b/dist/samples/3d-camera-position/jsfiddle/demo.js
new file mode 100644
index 000000000..3ef53de3c
--- /dev/null
+++ b/dist/samples/3d-camera-position/jsfiddle/demo.js
@@ -0,0 +1,126 @@
+'use strict';
+/*
+ * @license
+ * Copyright 2026 Google LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+async function initMap() {
+ // Declare the needed libraries.
+ await google.maps.importLibrary('maps3d');
+ const map3DElement = document.querySelector('gmp-map-3d');
+ // Elements from HTML
+ const headingSlider = document.getElementById('heading');
+ const tiltSlider = document.getElementById('tilt');
+ const rangeSlider = document.getElementById('range');
+ const latSlider = document.getElementById('lat');
+ const lngSlider = document.getElementById('lng');
+ const fovSlider = document.getElementById('fov');
+ const rollSlider = document.getElementById('roll');
+ const headingVal = document.getElementById('heading-val');
+ const tiltVal = document.getElementById('tilt-val');
+ const rangeVal = document.getElementById('range-val');
+ const altitudeVal = document.getElementById('altitude-val');
+ const fovVal = document.getElementById('fov-val');
+ const rollVal = document.getElementById('roll-val');
+ const codeElem = document.getElementById('generated-code');
+ const copyBtn = document.getElementById('copy-btn');
+ let currentAltitude = 30;
+ let isUserInteracting = false;
+ // Update values on UI when the map changes.
+ const updateUI = () => {
+ const heading = map3DElement.heading?.toFixed(0) ?? '0';
+ const tilt = map3DElement.tilt?.toFixed(0) ?? '0';
+ const range = map3DElement.range?.toFixed(0) ?? '0';
+ const rawFov = parseFloat(map3DElement.fov?.toFixed(0) ?? '45');
+ const fovClamped = Math.min(80, Math.max(5, rawFov));
+ const fov = fovClamped.toString();
+ const roll = map3DElement.roll?.toFixed(0) ?? '0';
+ const center = map3DElement.center;
+ const mode = map3DElement.mode;
+ headingVal.textContent = heading;
+ tiltVal.textContent = tilt;
+ rangeVal.textContent = range;
+ fovVal.textContent = fov;
+ rollVal.textContent = roll;
+ if (!isUserInteracting) {
+ fovSlider.value = fov;
+ headingSlider.value = heading;
+ tiltSlider.value = tilt;
+ rangeSlider.value = Math.min(10000, parseFloat(range)).toString();
+ rollSlider.value = roll;
+ }
+ if (center) {
+ const lat = center.lat.toFixed(4);
+ const lng = center.lng.toFixed(4);
+ const alt = currentAltitude.toFixed(0);
+ latSlider.value = lat;
+ lngSlider.value = lng;
+ altitudeVal.textContent = alt;
+ codeElem.textContent = ` `;
+ }
+ };
+ // Copy generated HTML to clipboard.
+ copyBtn.addEventListener('click', () => {
+ void navigator.clipboard.writeText(codeElem.textContent || '');
+ copyBtn.textContent = 'Copied!';
+ setTimeout(() => {
+ copyBtn.textContent = 'Copy HTML';
+ }, 2000);
+ });
+ // Listen to slider changes using event delegation.
+ const panel = document.querySelector('.panel');
+ panel.addEventListener('input', (e) => {
+ const target = e.target;
+ if (target.tagName !== 'INPUT') return;
+ isUserInteracting = true;
+ const prop = target.name;
+ const val = parseFloat(target.value);
+ if (prop === 'lat') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: val,
+ lng: currentCenter.lng,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'lng') {
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: val,
+ altitude: currentCenter.altitude,
+ };
+ }
+ } else if (prop === 'altitude') {
+ currentAltitude = val;
+ const currentCenter = map3DElement.center;
+ if (currentCenter) {
+ map3DElement.center = {
+ lat: currentCenter.lat,
+ lng: currentCenter.lng,
+ altitude: val,
+ };
+ }
+ } else {
+ map3DElement[prop] = val;
+ }
+ updateUI();
+ });
+ panel.addEventListener('change', (e) => {
+ const target = e.target;
+ if (target.tagName === 'INPUT') {
+ isUserInteracting = false;
+ }
+ });
+ // Update UI on camera change events.
+ map3DElement.addEventListener('gmp-headingchange', updateUI);
+ map3DElement.addEventListener('gmp-tiltchange', updateUI);
+ map3DElement.addEventListener('gmp-rangechange', updateUI);
+ map3DElement.addEventListener('gmp-fovchange', updateUI);
+ // Initial UI sync
+ setTimeout(updateUI, 500);
+}
+void initMap();
diff --git a/index.html b/index.html
index 02b817c0f..dd5dacffd 100644
--- a/index.html
+++ b/index.html
@@ -10,6 +10,7 @@ Maps JSAPI Samples
3d-accessibility-features
3d-camera-boundary
3d-camera-center
+ 3d-camera-position
3d-camera-to-around
3d-clamp-mode
3d-coverage-map
diff --git a/package-lock.json b/package-lock.json
index e73506db6..6f561b287 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -464,6 +464,10 @@
"resolved": "samples/3d-camera-center",
"link": true
},
+ "node_modules/@js-api-samples/3d-camera-position": {
+ "resolved": "samples/3d-camera-position",
+ "link": true
+ },
"node_modules/@js-api-samples/3d-camera-to-around": {
"resolved": "samples/3d-camera-to-around",
"link": true
@@ -5054,6 +5058,10 @@
"name": "@js-api-samples/3d-camera-center",
"version": "1.0.0"
},
+ "samples/3d-camera-position": {
+ "name": "@js-api-samples/3d-camera-position",
+ "version": "1.0.0"
+ },
"samples/3d-camera-to-around": {
"name": "@js-api-samples/3d-camera-to-around",
"version": "1.0.0"