Animate the camera around a point with 3D terrain
Use the FreeCamera
API to create a fly-over animation focused on a point.
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Animate the camera around a point with 3D terrain</title><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><link href="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet"><script src="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js"></script><style>body { margin: 0; padding: 0; }#map { position: absolute; top: 0; bottom: 0; width: 100%; }</style></head><body><div id="map"></div> <script> // TO MAKE THE MAP APPEAR YOU MUST // ADD YOUR ACCESS TOKEN FROM // https://account.mapbox.com mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';const map = new mapboxgl.Map({container: 'map',zoom: 11.53,center: [138.7189, 35.1691],pitch: 76,bearing: -177.2,// Choose from Mapbox's core styles, or make your own style with Mapbox Studiostyle: 'mapbox://styles/mapbox/satellite-v9',interactive: false}); map.on('style.load', () => {map.setFog({}); // Set the default atmosphere style // Add terrainmap.addSource('mapbox-dem', {'type': 'raster-dem','url': 'mapbox://mapbox.mapbox-terrain-dem-v1','tileSize': 512,'maxzoom': 14});map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });}); function updateCameraPosition(position, altitude, target) {const camera = map.getFreeCameraOptions(); camera.position = mapboxgl.MercatorCoordinate.fromLngLat(position,altitude);camera.lookAtPoint(target); map.setFreeCameraOptions(camera);} let animationIndex = 0;let animationTime = 0.0; // wait for the terrain to load before starting animationsmap.once('idle', () => {// linearly interpolate between two altitudes/positions based on timeconst lerp = (a, b, t) => {if (Array.isArray(a) && Array.isArray(b)) {const result = [];for (let i = 0; i < Math.min(a.length, b.length); i++)result[i] = a[i] * (1.0 - t) + b[i] * t;return result;} else {return a * (1.0 - t) + b * t;}}; const animations = [{duration: 20000.0,animate: (phase) => {const start = [138.73375, 35.41914];const end = [138.72649, 35.33974];const alt = [7000.0, 6000.0]; // interpolate camera position while keeping focus on a target lat/lngconst position = lerp(start, end, phase);const altitude = lerp(alt[0], alt[1], phase);const target = [138.73036, 35.36197]; updateCameraPosition(position, altitude, target);}},{duration: 15000.0,animate: (phase) => {const start = [138.72649, 35.33974];const end = [138.72623, 35.31977];const alt = [6000.0, 6000.0];const target1 = [138.73036, 35.36197];const target2 = [138.74831, 35.34784]; // interpolate both the camera position and targetconst position = lerp(start, end, phase);const altitude = lerp(alt[0], alt[1], phase);const target = lerp(target1, target2, phase); updateCameraPosition(position, altitude, target);}},{duration: 15000.0,animate: (phase) => {// create easing function for the animationconst easeInOutQuad = (t) => {return t < 0.5? 2.0 * t * t: (4.0 - 2.0 * t) * t - 1.0;};const start = [138.72623, 35.31977];const end = [138.73375, 35.41914];const alt = [6000.0, 7000.0];const target1 = [138.74831, 35.34784];const target2 = [138.73036, 35.36197]; // interpolate both the camera position and targetconst position = lerp(start, end, easeInOutQuad(phase));const altitude = lerp(alt[0], alt[1], phase);const target = lerp(target1, target2, phase); updateCameraPosition(position, altitude, target);}}]; let lastTime = 0.0;function frame(time) {animationIndex %= animations.length;const current = animations[animationIndex]; if (animationTime < current.duration) {// Normalize the duration between 0 and 1 to interpolate the animationconst phase = animationTime / current.duration;current.animate(phase);} // Elasped time since last frame, in millisecondsconst elapsed = time - lastTime;animationTime += elapsed;lastTime = time; if (animationTime > current.duration) {animationIndex++;animationTime = 0.0;} window.requestAnimationFrame(frame);} window.requestAnimationFrame(frame);});</script> </body></html>
Was this example helpful?