### Start Debug Server Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Starts the development server for the Mapbox GL JS debug page. Replace {YOUR_MAPBOX_ACCESS_TOKEN} with your actual token. ```bash MAPBOX_ACCESS_TOKEN={YOUR_MAPBOX_ACCESS_TOKEN} npm start ``` -------------------------------- ### Install Mapbox GL Style Specification Source: https://github.com/mapbox/mapbox-gl-js/blob/main/src/style-spec/README.md Commands to install the style specification package locally or globally to access CLI utilities. ```bash npm install @mapbox/mapbox-gl-style-spec npm install @mapbox/mapbox-gl-style-spec --global ``` -------------------------------- ### Start harp static file server Source: https://github.com/mapbox/mapbox-gl-js/blob/main/test/integration/README.md Starts a simple static file server using the 'harp' utility. This server is used to serve local files, typically vector tiles, for testing and inspection purposes. ```bash harp server . ``` -------------------------------- ### Install vt2geojson and harp Source: https://github.com/mapbox/mapbox-gl-js/blob/main/test/integration/README.md Installs the necessary command-line utilities for processing vector tiles and serving files. These tools are essential for reading and inspecting vector tile data. ```bash npm install -g vt2geojson harp ``` -------------------------------- ### Install Node Version Manager (nvm) Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Installs nvm, a tool for managing multiple Node.js versions. ```bash nvm install ``` -------------------------------- ### Install Development Dependencies (Linux) Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Installs Git, Make, and necessary development libraries on Debian-based Linux systems. ```bash sudo apt-get update sudo apt-get install build-essential git libglew-dev libxi-dev ``` -------------------------------- ### Development Commands for Mapbox GL JS Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CLAUDE.md Essential npm commands for starting the development server and building the project in various formats. ```bash npm start npm run build-esm-dev npm run build-esm-prod npm run build-prod # UMD build npm run build-css npm run codegen ``` -------------------------------- ### Install Xcode Command Line Tools (OSX) Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Installs essential command-line developer tools on macOS. ```bash xcode-select --install ``` -------------------------------- ### Video Export Setup and Recording Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/video-export.html Sets up the map for video recording by adding a DEM source, configuring terrain, and initializing an H.264 encoder. It then hooks into the 'render' event to capture frames and encode them. ```javascript import loadEncoder from 'https://unpkg.com/mp4-h264@1.0.7/build/mp4-encoder.js'; import {simd} from "https://unpkg.com/wasm-feature-detect?module"; map.on('load', async () => { map.addSource('dem', { type: 'raster-dem', url: 'mapbox://mapbox.mapbox-terrain-dem-v1' }); map.setTerrain({ source: 'dem', exaggeration: 1.5 }); // wait until the map settles await map.once('idle'); // uncomment to fine-tune animation without recording: // animate(); return; // don't forget to enable WebAssembly SIMD in chrome://flags for faster encoding const supportsSIMD = await simd(); // initialize H264 video encoder const Encoder = await loadEncoder({simd: supportsSIMD}); const gl = map.painter.context.gl; const width = gl.drawingBufferWidth; const height = gl.drawingBufferHeight; const encoder = Encoder.create({ width: width, height: height, fps: 60, kbps: 64000, rgbFlipY: true }); // stub performance.now for deterministic rendering per-frame (only available in dev build) let now = performance.now(); mapboxgl.setNow(now); const ptr = encoder.getRGBPointer(); // keep a pointer to encoder WebAssembly heap memory function frame() { // increment stub time by 16.6ms (60 fps) now += 1000 / 60; mapboxgl.setNow(now); const pixels = encoder.memory().subarray(ptr); // get a view into encoder memory gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); // read pixels into encoder encoder.encodeRGBPointer(); // encode the frame } map.on('render', frame); // set up frame-by-frame recording await animate(); // stop recording map.off('render', frame); mapboxgl.restoreNow(); // download the encoded video file const mp4 = encoder.end(); const anchor = document.createElement("a"); anchor.href = URL.createObjectURL(new Blob([mp4], {type: "video/mp4"})); anchor.download = "mapbox-gl"; anchor.click(); // make sure to run `ffmpeg -i mapbox-gl.mp4 mapbox-gl-optimized.mp4` to compress the video }); ``` -------------------------------- ### Install Node Module Dependencies Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Installs all necessary Node.js package dependencies for the project. ```bash npm install ``` -------------------------------- ### Map Initialization and Clustering Setup Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/cluster.html Initializes a Mapbox GL JS map with clustering enabled and configures sources and layers for displaying clustered data. This setup is used for visualizing data points that are grouped together at various zoom levels. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; var map = window.map = new mapboxgl.Map({ accessToken: getAccessToken(), container: 'map', devtools: true, zoom: 1, center: [0, 0], style: 'mapbox://styles/mapbox/cjf4m44iw0uza2spb3q0a7s41', hash: true }); map.on('load', () => { map.addSource('geojson', { "type": "geojson", "data": "/test/integration/data/places.geojson", "cluster": true, "clusterRadius": 50, "clusterProperties": { "max": ["max", ["get", "scalerank"]], "sum": ["+", ["get", "scalerank"]], "has_island": ["any", ["==", ["get", "featureclass"], "island"]] } }); map.addLayer({ "id": "cluster", "type": "circle", "source": "geojson", "filter": ["==", "cluster", true], "paint": { "circle-color": ["case", ["get", "has_island"], "orange", "rgba(0, 200, 0, 1)"], "circle-radius": 20 } }); map.addLayer({ "id": "cluster_label", "type": "symbol", "source": "geojson", "filter": ["==", "cluster", true], "layout": { "text-field": "{point_count} ({max})", "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"], "text-size": 12, "text-allow-overlap": true, "text-ignore-placement": true } }); map.addLayer({ "id": "unclustered_point", "type": "circle", "source": "geojson", "filter": ["!=", "cluster", true], "paint": { "circle-color": "rgb(0, 0, 200)", "circle-radius": 10 } }); var hoverData = { "type": "FeatureCollection", "features": [] }; map.addSource('cluster_children', { "type": "geojson", "data": hoverData }); map.addLayer({ "id": "cluster_children", "type": "circle", "source": "cluster_children", "paint": { "circle-color": "rgb(0, 150, 0)", "circle-radius": 7 } }); function updateHover(features) { hoverData.features = features; map.getSource('cluster_children').setData(hoverData); } map.on('click', 'cluster', (e) => { var feature = e.features[0]; map.getSource('geojson').getClusterExpansionZoom(feature.properties.cluster_id, (err, zoom) => { if (err) throw err; updateHover([]); map.easeTo({ center: feature.geometry.coordinates, zoom }); }); }); map.on('mouseenter', 'cluster', (e) => { map.getCanvas().style.cursor = 'pointer'; map.getSource('geojson').getClusterLeaves(e.features[0].properties.cluster_id, Infinity, 0, (err, features) => { if (err) throw err; updateHover(features); }); }); map.on('mouseleave', 'cluster', (e) => { map.getCanvas().style.cursor = ''; updateHover([]); }); }); map.addControl(new mapboxgl.NavigationControl()); map.addControl(new mapboxgl.GeolocateControl()); ``` -------------------------------- ### Initialize Mapbox GL JS with CSP Source: https://github.com/mapbox/mapbox-gl-js/blob/main/test/integration/csp-tests/fixtures/csp.html This snippet demonstrates the basic setup for initializing a Mapbox GL JS map within a CSP-compliant environment. It includes fetching the access token and setting up a message event listener for map loading. ```javascript import {getAccessToken} from '../debug/access_token_generated.js'; mapboxgl.accessToken = getAccessToken(); window.addEventListener('message', (e) => { if (e.data.type === 'load') { const map = new mapboxgl.Map({ container: 'map', style: e.data.payload, center: [-74.006, 40.7128], // NYC zoom: 16, pitch: 60, performanceMetricsCollection: false }); map.once('load', () => { window.parent.postMessage({type: "map.load"}); }); } }); ``` -------------------------------- ### Map Initialization and Setup Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/animate-point-along-route.html Initializes a Mapbox GL JS map with specified access token, container, style, center, and zoom level. It also defines origin and destination points and a basic route as a LineString. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; /* globals turf */ const map = new mapboxgl.Map({ accessToken: getAccessToken(), container: 'map', devtools: true, style: 'mapbox://styles/mapbox/streets-v11', center: [-96, 37.8], zoom: 2.5 }); // San Francisco const origin = [-122.414, 37.776]; // Washington DC const destination = [-77.032, 38.913]; // A simple line from origin to destination. const route = { 'type': 'FeatureCollection', 'features': [ { 'type': 'Feature', 'geometry': { 'type': 'LineString', 'coordinates': [origin, destination] } } ] }; // A single point that animates along the route. // Coordinates are initially set to origin. const point = { 'type': 'FeatureCollection', 'features': [ { 'type': 'Feature', 'properties': {}, 'geometry': { 'type': 'Point', 'coordinates': origin } } ] }; ``` -------------------------------- ### Initialize Map and Add Raster Particle Layer Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/raster-particle-layer.html Sets up the Mapbox map, adds a raster-array source, and configures a raster-particle layer with initial paint properties. This is the primary setup for visualizing wind data. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; const PARAMS = { projection: 'globe', showTileBoundaries: false, fadeOpacityFactor: 0.98, speedFactor: 0.6, maxSpeed: 40, resetRateFactor: 0.4, particleCount: 2048, bandIndex: 0, elevation: 0, }; const RASTERARRAY_LAYER = '10winds'; window.onload = function() { const gui = new window.Tweakpane.Pane({ // eslint-disable-line container: document.querySelector('#config'), title: 'Particle animation settings' }); const fillOptions = (styles) => { const options = {}; for (const style of styles) { options[style] = style; } return options; }; const projectionDropdown = gui.addInput(PARAMS, 'projection', { options: fillOptions([ 'mercator', 'globe' ]) }); projectionDropdown.on('change', (ev) => { map.setProjection(ev.value); }); const showTileBoundaries = gui.addInput(PARAMS, 'showTileBoundaries'); showTileBoundaries.on('change', (ev) => { map.showTileBoundaries = ev.value; }); const opacitySlider = gui.addInput(PARAMS, 'fadeOpacityFactor', { min: 0.0, max: 1.0 }); opacitySlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-fade-opacity-factor', ev.value); }); const speedFactorSlider = gui.addInput(PARAMS, 'speedFactor', { min: 0.0, max: 1.0 }); speedFactorSlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-speed-factor', ev.value); }); const maxSpeedSlider = gui.addInput(PARAMS, 'maxSpeed', { min: 1.0, max: 140.0 }); maxSpeedSlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-max-speed', ev.value); }); const dropRateSlider = gui.addInput(PARAMS, 'resetRateFactor', { min: 0.0, max: 1.0 }); dropRateSlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-reset-rate-factor', ev.value); }); const particleCountSlider = gui.addInput(PARAMS, 'particleCount', { min: 64, max: 4096 }); particleCountSlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-count', ev.value); }); let bandSlider; let bandList; map.on('sourcedata', ({sourceId}) => { const layer = map.getSource(sourceId)?.rasterLayers?.find(({id}) => id === RASTERARRAY_LAYER); if (!layer?.fields?.bands) return; // Exit early if the list of bands is unchanged if (JSON.stringify(layer.fields.bands) === JSON.stringify(bandList)) return; bandList = layer.fields.bands; // Remove the existing slider before recreating if (bandSlider) bandSlider.dispose(); // Create a new band slider with the updated list bandSlider = gui.addInput(PARAMS, 'bandIndex', { min: 0, max: bandList.length - 1, step: 1 }); bandSlider.on('change', ({value}) => { map.setPaintProperty('wind-layer', 'raster-particle-array-band', bandList[value]); }); }); const elevationSlider = gui.addInput(PARAMS, 'elevation', { min: 0, max: 1000000 }); elevationSlider.on('change', (ev) => { map.setPaintProperty('wind-layer', 'raster-particle-elevation', ev.value); }); }; const map = new mapboxgl.Map({ accessToken: getAccessToken(), container: 'map', maxZoom: 2, minZoom: 2, zoom: 2, center: [-28, 47], // Choose from Mapbox's core styles, or make your own style with Mapbox Studio style: 'mapbox://styles/mapbox/dark-v11' }); map.on('load', () => { map.addSource('raster-array-source', { 'type': 'raster-array', 'url': 'mapbox://rasterarrayexamples.gfs-winds', 'tileSize': 512 }); map.addLayer({ 'id': 'wind-layer', 'type': 'raster-particle', 'source': 'raster-array-source', 'source-layer': RASTERARRAY_LAYER, 'paint': { 'raster-particle-speed-factor': PARAMS.speedFactor, 'raster-particle-fade-opacity-factor': PARAMS.fadeOpacityFactor, 'raster-particle-reset-rate-factor': PARAMS.resetRateFactor, 'raster-particle-count': PARAMS.particleCount, 'raster-particle-max-speed': 40, 'raster-particle-color': [ 'interpolate', ['linear'], ['raster-particle-speed'], 1.5, 'rgba(134,163,171,256)', 2.5, 'rgba(126,152,188,256)', 4.12, 'rgba(110,143,208,256)', 4.63, 'rgba(110,143,208,256)', 6.17, 'rgba(15,147,167,256)', 7.72, 'rgba(15,147,167,256)', 9.26, 'rgba(57,163,57,256)', 10.29, 'rgba(57,163,57,256)', 11.83, 'rgba(194,134,62,256)', 13.37, 'rgba(194,134,63,256)', 14.92, 'rgba(200,66,13,256)', 16.46, 'rgba(200,66,13,256)', 18.0, 'rgba(210,0,50,256)', 20.06, 'rgba(215,0,50,256)', 21.6, 'rgba(175,80,136,256)', 23.66, 'rgba(175,80,136,256)', 25.21, 'rgba(117,74,147,256)', 27.78, 'rgba(117,74,147,256)', 29.32, 'rgba(68,105,141,256)', 31.89, 'rgba(68,105,141,256)', 33.44, 'rgba(194,251,119,256)', 42.18, 'rgba(194,251,119,256)', 43.72, 'rgba(241,255,109,256)', 48.87, 'rgba(241,255,109,256)', 50.41, 'rgba(256,256,256,256)', 57.61, 'rgba(256,256,256,256)', 59.16, 'rgba(0,256,256,256)', 68.93, 'rgba(0,256,256,256)', 69.44, 'rgba(256,37,256,256)' ] } }); }); ``` -------------------------------- ### Map Load and Terrain Setup Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/camera-for-bounds.html Handles the map's load event to add a GeoJSON layer for visualizing drawn bounds, set up terrain using Mapbox DEM, and initialize the drawing controls with an initial bounding box. ```javascript map.on('load', function() { map.addLayer({ 'id': 'bbox', 'type': 'line', 'source': { 'type': 'geojson', data }, 'layout': {}, 'paint': { 'line-color': 'red', 'line-width': 2 } }); map.setFog({}); map.addSource('mapbox-dem', { 'type': 'raster-dem', 'url': 'mapbox://mapbox.terrain-rgb', 'tileSize': 512, 'maxzoom': 14 }); map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 }); draw.set(turf.featureCollection([ turf.bboxPolygon(initialBbox) ])); updatePolygon(); }); ``` -------------------------------- ### Mapbox GL JS Map Setup and Query Test Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/query-test.html This snippet sets up a Mapbox GL JS map, loads a style, applies operations, and performs a query on rendered features. It's useful for testing query functionality with various options. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; import {applyOperations} from '../test/integration/lib/operation-handlers.js'; import {transformRequest as baseTransformRequest} from '../test/integration/lib/transform-request.js'; function transformRequest(url, resourceTypeEnum) { const req = baseTransformRequest(url, resourceTypeEnum); return { url: req.url.replace(location.origin, `${location.origin}/test/integration/`) }; } async function fetchStyle() { let test = new URLSearchParams(location.search).get('test'); if (!test) test = prompt('test name:', 'geometry/point'); const response = await fetch(`../test/integration/query-tests/${test}/style.json`); const style = await response.json(); history.replaceState({}, '', `${location.pathname}?test=${test}`); console.log(style); return style; } const style = await fetchStyle(); const {width, height, fadeDuration = 0, localIdeographFontFamily = false, operations, scaleFactor = 1, ...options} = style.metadata.test; const container = document.getElementById('map'); container.style.width = width + 'px'; container.style.height = height + 'px'; const map = window.map = new mapboxgl.Map({ accessToken: getAccessToken(), container, style, transformRequest, fadeDuration, localIdeographFontFamily, interactive: false, attributionControl: false, performanceMetricsCollection: false, scaleFactor }); map.removeControl(map._logoControl); map.on('click', (e) => { console.log(e.point); }); map.on('error', (e) => { console.error(e); }); map._authenticate = () => {}; // override internal timing to enable precise wait operations window._renderTestNow = 0; mapboxgl.setNow(window._renderTestNow); if (options.debug) { map.showParseStatus = false; map.showTileBoundaries = true; map.showCollisionBoxes = true; } if (options.showOverdrawInspector) map.showOverdrawInspector = true; if (options.showTerrainWireframe) map.showTerrainWireframe = true; if (options.showLayers2DWireframe) map.showLayers2DWireframe = true; if (options.showLayers3DWireframe) map.showLayers3DWireframe = true; if (options.showElevationIdDebug) map.showElevationIdDebug = true; if (options.showPadding) map.showPadding = true; if (options.collisionDebug) map.showCollisionBoxes = true; if (options.fadeDuration) map._isInitialLoad = false; if (options.forceEmissiveFallback) { map.painter._forceEmissiveMode = true; map.painter.emissiveMode = 'mrt-fallback'; } map.repaint = true; await map.once('load'); await applyOperations(map, style.metadata.test); map.repaint = true; await new Promise(resolve => requestAnimationFrame(map._requestDomTask.bind(map, resolve))); // Perform query operation and compare results from expected values if (options.queryOptions) { console.log(`queryRenderedFeatures(${JSON.stringify(options.queryGeometry)}, ${JSON.stringify(options.queryOptions)});`); } else { console.log(`queryRenderedFeatures(${JSON.stringify(options.queryGeometry)});`); } const results = options.queryGeometry ? map.queryRenderedFeatures(options.queryGeometry, options.queryOptions || {}) : []; console.log(results); ``` -------------------------------- ### Create Standalone Build Source: https://github.com/mapbox/mapbox-gl-js/blob/main/CONTRIBUTING.md Generates production-ready `mapbox-gl.js` and `mapbox-gl.css` files. ```bash npm run build-prod npm run build-css ``` -------------------------------- ### Development Commands Source: https://github.com/mapbox/mapbox-gl-js/blob/main/plugins/mapbox-gl-pmtiles-provider/README.md Run these commands to build the project bundle and execute unit tests during development. ```bash npm run build # Build the bundle npm test # Run unit tests ``` -------------------------------- ### Initialize Dat.GUI for Controls Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/shadows.html Sets up a dat.GUI interface to control map lighting and terrain properties. It adds folders for 'Lighting' and 'Terrain' with various adjustable parameters. ```javascript window.onload = function() { const gui = window.gui = new dat.GUI({autoPlace: false}); document.getElementById('container').appendChild(gui.domElement); const lights = gui.addFolder('Lighting'); const castShadows = lights.add(pageSettings, 'castShadows'); castShadows.onFinishChange((value) => { updateLights(); }); const shadowIntensity = lights.add(pageSettings, 'shadowIntensity', 0.0, 1.0); shadowIntensity.onChange((value) => { updateLights(); }); const sunPolarAngle = lights.add(pageSettings, 'sunPolarAngle', 0.0, 90.0); sunPolarAngle.onChange((value) => { updateLights(); }); const sunBearing = lights.add(pageSettings, 'sunBearing', 0.0, 360.0); sunBearing.onChange((value) => { updateLights(); }); const sunIntensity = lights.add(pageSettings, 'sunIntensity', 0.0, 1.0); sunIntensity.onChange((value) => { updateLights(); }); const sunColor = lights.addColor(pageSettings, 'sunColor'); sunColor.onChange((value) => { updateLights(); }); const ambientIntensity = lights.add(pageSettings, 'ambientIntensity', 0.0, 1.0); ambientIntensity.onChange((value) => { updateLights(); }); const ambientColor = lights.addColor(pageSettings, 'ambientColor'); ambientColor.onChange((value) => { updateLights(); }); const terrain = gui.addFolder('Terrain'); const enableTerrain = terrain.add(pageSettings, 'enableTerrain'); enableTerrain.onFinishChange((value) => { map.setTerrain(value ? {"source": "mapbox-dem", "exaggeration": pageSettings.terrainExaggeration} : null); }); const terrainExaggeration = terrain.add(pageSettings, 'terrainExaggeration', 0, 5); terrainExaggeration.onChange((value) => { if (pageSettings.enableTerrain) { map.setTerrain({"source": "mapbox-dem", "exaggeration": value}); } }); }; ``` -------------------------------- ### Initialize Map and Add Line Layer with Pattern Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/line-pattern.html Sets up a Mapbox map and adds a line layer with a custom pattern. Requires a Mapbox access token and the mapbox-gl library. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; const lineBaseWidth = 16; const zoomConstExpression = { "type": "exponential", "base": 2, "stops": [ [0, lineBaseWidth * 1], [1, lineBaseWidth * 2], [1, lineBaseWidth * 1], [2, lineBaseWidth * 2], [2, lineBaseWidth * 1], [3, lineBaseWidth * 2], [3, lineBaseWidth * 1], [4, lineBaseWidth * 2], [4, lineBaseWidth * 1], [5, lineBaseWidth * 2], [5, lineBaseWidth * 1], [6, lineBaseWidth * 2], [6, lineBaseWidth * 1], [7, lineBaseWidth * 2], [7, lineBaseWidth * 1], [8, lineBaseWidth * 2], [8, lineBaseWidth * 1], [9, lineBaseWidth * 2], [9, lineBaseWidth * 1], [10, lineBaseWidth * 2], [10, lineBaseWidth * 1], [11, lineBaseWidth * 2], [11, lineBaseWidth * 1], [12, lineBaseWidth * 2], [12, lineBaseWidth * 1], [13, lineBaseWidth * 2], [13, lineBaseWidth * 1], [14, lineBaseWidth * 2], [14, lineBaseWidth * 1], [15, lineBaseWidth * 2], [15, lineBaseWidth * 1], [16, lineBaseWidth * 2], [16, lineBaseWidth * 1], [17, lineBaseWidth * 2], [17, lineBaseWidth * 1], [18, lineBaseWidth * 2], [18, lineBaseWidth * 1], [19, lineBaseWidth * 2], [19, lineBaseWidth * 1], [20, lineBaseWidth * 2], [20, lineBaseWidth * 1], [21, lineBaseWidth * 2], [21, lineBaseWidth * 1], [22, lineBaseWidth * 2] ] }; const PatternDemo = function() { this.useZoomLevelConstantWidth = true; this.terrain = false; this.elevatedLine = false; }; const patternDemo = new PatternDemo(); window.onload = function() { const gui = new Tweakpane.Pane({ // eslint-disable-line container: document.querySelector('#config'), title: 'Parameters', }); gui.addInput(patternDemo, 'useZoomLevelConstantWidth').on('change', (ev) => { if (patternDemo.useZoomLevelConstantWidth) { map.setPaintProperty('route', 'line-width', zoomConstExpression); } else { map.setPaintProperty('route', 'line-width', lineBaseWidth); } }); gui.addInput(patternDemo, 'terrain').on('change', (ev) => { if (patternDemo.terrain) { map.setTerrain({"exaggeration" : 2.5, source: 'mapbox-dem'}); } else { map.setTerrain(null); } }); gui.addInput(patternDemo, 'elevatedLine').on('change', (ev) => { map.setLayoutProperty('route0', 'line-z-offset', patternDemo.elevatedLine ? 0.01 : 0); map.setLayoutProperty('route', 'line-z-offset', patternDemo.elevatedLine ? 0.01 : 0); }); }; const map = window.map = new mapboxgl.Map({ accessToken: getAccessToken(), container: 'map', devtools: true, style: 'mapbox://styles/mapbox/standard', hash: true, center: [2.3406, 48.8542], zoom: 16 }); const route = { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {}, "geometry": { "coordinates": [ [2.334249, 48.858044], [2.335224, 48.857798], [2.336232, 48.857873], [2.336069, 48.857606], [2.336378, 48.857488], [2.336492, 48.857285], [2.336524, 48.857061], [2.336719, 48.855681], [2.334201, 48.855938], [2.333941, 48.855510], [2.336118, 48.854773], [2.335484, 48.854045], [2.335923, 48.853971], [2.335322, 48.853308], [2.336979, 48.852912], [2.336931, 48.853842], [2.337337, 48.853842], [2.338361, 48.853682], [2.337743, 48.855275], [2.339953, 48.856419], [2.340441, 48.856098], [2.339856, 48.855371], [2.340928, 48.854644], [2.340717, 48.854398], [2.340555, 48.854217], [2.340148, 48.853457], [2.342099, 48.853329], [2.342700, 48.853276], [2.343236, 48.853190], [2.343285, 48.853104], [2.343224, 48.852862], [2.342905, 48.852395], [2.342626, 48.852088], [2.342014, 48.851686], [2.345523, 48.850850], [2.345935, 48.850962], [2.346245, 48.851090], [2.347629, 48.851658], [2.347862, 48.851806], [2.348203, 48.852287], [2.348103, 48.852309], [2.348060, 48.852311], [2.348049, 48.852212], [2.347870, 48.851980], [2.347767, 48.852019], [2.347665, 48.851941], [2.347364, 48.852139], [2.347298, 48.852107], [2.347011, 48.852190], [2.346923, 48.852195], [2.347571, 48.852569], [2.347528, 48.852588], [2.347693, 48.852680], [2.346974, 48.853039], [2.347011, 48.853065], [2.346954, 48.853103], [2.346761, 48.853189], [2.346789, 48.853213], [2.346948, 48.853498], [2.347170, 48.853446], [2.347153, 48.853425], [2.347181, 48.853399], [2.348236, 48.852909], [2.348370, 48.852849], [2.348469, 48.852810], [2.348469, 48.852776], [2.348225, 48.852461], [2.348304, 48.852415], [2.348279, 48.852387], [2.348573, 48.852270], [2.349232, 48.851974], [2.349301, 48.851946], [2.349229, 48.851854], [2.349164, 48.851860] ], "type": "LineString" }} ]}; const longRoute = { "type": "FeatureCollection", "features": [ { "type": "Feature", ``` -------------------------------- ### Initialize Tweakpane GUI Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/3d-playground.html Creates a Tweakpane instance to manage and display adjustable parameters for the 3D map configuration. The pane is configured to be appended to a specific DOM element. ```javascript window.onload = function() { const gui = new Tweakpane.Pane({ container: document.querySelector('#config'), title: 'Parameters', }); const fillOptions = (styles) => { const options = {}; for (const style of styles) { options[style] = ``` -------------------------------- ### Start and Stop Pathological FlyTo Animations Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/pathological-flyto.html Initiates and cancels a continuous loop of flyTo animations with random destinations. Use this to stress-test the flyTo method. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; let goat = 0; let pleaseStop = null; let totals = []; document.getElementById("start").addEventListener("click", () => { totals = []; pleaseStop = setInterval(() => { if ((goat % 2) === 0) { map.flyTo({ center: [-122.41381885225483 + Math.random() * 20, 37.73787623085941], zoom: 16, duration: 7000, preloadOnly: false }); } else { map.flyTo({ center: [148.44217489435937 - Math.random() * 10, -35.721640804238895], zoom: 16, duration: 7000, preloadOnly: false }); } goat++; }, 5000); }); document.getElementById("cancel").addEventListener("click", () => { window.pleaseStop = clearInterval(pleaseStop); }); ``` -------------------------------- ### Using Mapbox GL Shader Pragmas Source: https://github.com/mapbox/mapbox-gl-js/blob/main/src/shaders/README.md Demonstrates the syntax for defining and initializing shader variables using Mapbox-specific pragmas. These pragmas handle the underlying GLSL variable types based on context requirements. ```glsl #pragma mapbox: define highp vec4 color main() { #pragma mapbox: initialize highp vec4 color ... gl_FragColor = color; } ``` -------------------------------- ### Initialize Mapbox GL JS with Globe Projection Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/globe-fill-extrusion.html Initializes a Mapbox GL JS map with the 'globe' projection. Includes setup for terrain, ambient occlusion, and lighting. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; var map = window.map = new mapboxgl.Map({ accessToken: getAccessToken(), container: 'map', devtools: true, zoom: 12.5, center: [-122.4194, 37.7749], style: 'mapbox://styles/endanke/ckw0r1ywi3f3b14mpoly55wjc', hash: true, projection: 'globe' }); ``` -------------------------------- ### Import Mapbox GL JS and Access Token Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/canvas.html Imports the Mapbox GL JS library and a function to get the access token. These are necessary for initializing and using the map. ```javascript import * as mapboxgl from '../dist/esm-dev/mapbox-gl.js'; import {getAccessToken} from './access_token_generated.js'; ``` -------------------------------- ### Preload and Run easeTo Animation Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/preload-tiles.html Shows how to preload an easeTo animation to a different center and zoom, and then execute it. Button text changes to reflect the preload and execution states. ```javascript const easeToOptions = { center: [-119.63, 37.74], zoom: 10, duration: 5000 }; document.getElementById('easeTo-preload').onclick = async function () { this.innerText = 'Preload easeTo 🔄'; map.easeTo({...easeToOptions, preloadOnly: true}); await map.once('idle'); this.innerText = 'Preload easeTo ✅'; }; document.getElementById('easeTo-run').onclick = async function () { this.innerText = 'Run easeTo 🔄'; map.easeTo(easeToOptions); await map.once('idle'); this.innerText = 'Run easeTo ✅'; }; ``` -------------------------------- ### Initialize Dat.GUI for Map Controls Source: https://github.com/mapbox/mapbox-gl-js/blob/main/debug/measure-light.html Sets up a dat.GUI interface to control map properties like style, lighting, and terrain. The GUI elements are appended to a specific container. ```javascript window.onload = function() { var gui = new dat.GUI({autoPlace: false}); // eslint-disable-line document.getElementById('container').appendChild(gui.domElement); var style = gui.add(demo3d, 'style', [ 'mapbox/streets-v11', 'mapbox/streets-v12', 'mapbox/satellite-streets-v11', 'mapbox/satellite-streets-v12', 'mapbox/light-v10', 'mapbox/light-v11', 'mapbox/dark-v10', 'mapbox/dark-v11', 'mapbox/outdoors-v11', 'mapbox/outdoors-v12', 'mapbox/satellite-v9', 'mapbox/satellite-v10', 'mapbox-map-design/ckhqrdj3q0q1y19ko8t70qtqu', 'mapbox-map-design/ckhqrf2tz0dt119ny6azh975y', 'mapbox-map-design/ckhqrbxlc1awj19svtb92m0bd' ]); style.onFinishChange((value) => { map.setStyle('mapbox://styles/' + value); }); var lights = gui.addFolder('3D Lights'); var enable3dLights = lights.add(demo3d, 'enable3dLights'); enable3dLights.onFinishChange((value) => { updateLights(value); }); var directionalLightAltitude = lights.add(demo3d, 'directionalLightAltitude', 0.0, 90.0); directionalLightAltitude.onChange((value) => { updateLights(demo3d.enable3dLights); }); var directionalLightAzimuth = lights.add(demo3d, 'directionalLightAzimuth', 0.0, 360.0); directionalLightAzimuth.onChange((value) => { updateLights(demo3d.enable3dLights); }); var directionalLightIntensity = lights.add(demo3d, 'directionalLightIntensity', 0.0, 1.0); directionalLightIntensity.onChange((value) => { updateLights(demo3d.enable3dLights); }); var directionalLightColor = lights.addColor(demo3d, 'directionalLightColor'); directionalLightColor.onChange((value) => { updateLights(demo3d.enable3dLights); }); var ambientLightIntensity = lights.add(demo3d, 'ambientLightIntensity', 0.0, 1.0); ambientLightIntensity.onChange((value) => { updateLights(demo3d.enable3dLights); }); var ambientLightColor = lights.addColor(demo3d, 'ambientLightColor'); ambientLightColor.onChange((value) => { updateLights(demo3d.enable3dLights); }); var terrain = gui.addFolder('Terrain'); var enableTerrain = terrain.add(demo3d, 'enableTerrain'); enableTerrain.onFinishChange((value) => { map.setTerrain(value ? {"source": 'mapbox-dem', "exaggeration": demo3d.terrainExaggeration} : null); }); var terrainExaggeration = terrain.add(demo3d, 'terrainExaggeration', 0.0, 10.0); terrainExaggeration.onFinishChange((value) => { map.setTerrain(demo3d.enableTerrain ? {"source": "mapbox-dem", "exaggeration": demo3d.terrainExaggeration} : null); }); var symbolElevationGroup = gui.addFolder('Symbol Elevation'); var symbolElevation = symbolElevationGroup.add(demo3d, 'symbolZOffset', 0.0, 1000.0); symbolElevation.onChange((value) => { map.setPaintProperty('icon-variant-label-demo', 'symbol-z-offset', demo3d.symbolZOffset); }); var symbolElevationReference = symbolElevationGroup.add(demo3d, 'symbolElevationReference', ['sea', 'ground']); symbolElevationReference.onChange((value) => { map.setLayoutProperty('icon-variant-label-demo', 'symbol-elevation-reference', demo3d.symbolElevationReference); }); }; ```