Mapbox GL JS
repository·main·Indexed 11 days ago
https://github.com/mapbox/mapbox-gl-jsA high-performance WebGL-based JavaScript library for rendering interactive vector maps. Version 3.28.1 uses the Mapbox Style and Vector Tile specifications to provide customizable map experiences, including 3D terrain and data-driven styling.
What's inside Mapbox GL JS
- Mapbox GL JS is a JavaScript library designed for creating interactive, customizable vector maps on the web. It functions by taking map styles that follow the Mapbox Style Specification and applying them to vector tiles that follow the Mapbox Vector Tile Specification. The rendering is performed using WebGL, enabling high-performance map visualizations including 3D terrain, data-driven styling, and complex layers.
Use @mapbox/mapbox-gl-pmtiles-provider to read PMTiles archives
mainThe@mapbox/mapbox-gl-pmtiles-provideris a tile provider for Mapbox GL JS that implements theTileProviderinterface. It allows Mapbox GL JS to read vector tiles directly from PMTiles archives, enabling efficient serving of tile data from single archive files.How vector tile rendering works
mainVector tile rendering in Mapbox GL JS is a multi-stage process that splits heavy computation (parsing and layout) onto WebWorker threads to keep the main thread responsive.
1. Parsing and Layout (Worker Thread)
Vector tiles are fetched and processed in WebWorkers through the following steps:
- Deserialization: Source layers, feature properties, and geometries are extracted from the PBF format (using
@mapbox/vector-tile). - Layout: Data is transformed into render-ready formats used by WebGL shaders. This is managed by
WorkerTile,Bucketclasses, andProgramConfiguration. - Indexing: Geometries are indexed into a
FeatureIndexto enable spatial queries likequeryRenderedFeatures. - Bucketing:
WorkerTile#parse()creates aBucketfor each 'family' of style layers that share the same underlying features and layout properties.
2. Rendering (Main Thread)
Once layout is complete, data is transferred to the main thread. The
Bucketserves as the single point of knowledge for turning vector tiles into WebGL buffers, holding vertex and element array data inArrayGroupobjects.Rendering follows this flow:
- Pass Management:
Painter#renderPass()iterates through style layers. - Layer Drawing: The painter delegates to layer-specific
drawXxxx()methods (e.g.,drawLine,drawSymbol). - WebGL Execution: For each tile, the drawer obtains a shader program from the
Painter, sets uniform values based on style properties, binds layout buffer data viaBufferGroup, and executesgl.drawElements().
- Deserialization: Source layers, feature properties, and geometries are extracted from the PBF format (using
Understand the data structure of a Tile and its Buckets
mainWhen vector tile data is transferred from the worker to the main thread, it is organized into a hierarchy of Tiles and Buckets. A single
Tilecontains multipleBucketinstances. ABucketrepresents a group of style layers that share the same layout 'family'.The data structure follows this pattern:
Tile | +- buckets[layer-id]: Bucket | | | + ArrayGroup { | globalProperties: { zoom } | layoutVertexArray, | indexArray, | indexArray2, | layerData: { | [style layer id]: { | programConfiguration, | paintVertexArray, | paintPropertyStatistics | } | ... | } | } | +- buckets[...]: Bucket ...Note: A particular bucket may appear multiple times in
tile.buckets—once for each layer in a given layout 'family'.Use Mapbox GL pragmas to manage variable scope and types
mainMapbox GL Shaders use pragmas to abstract over how variables are declared based on their context (e.g., whether they are
uniforms,attributes, orvaryings). This allows you to write shader code that works regardless of whether a variable is constant for all features or unique to each feature.Pragma Syntax
Pragmas follow this pattern:
#pragma mapbox: (define|initialize) (lowp|mediump|highp) (float|vec2|vec3|vec4) {name}Usage Requirements
To correctly use pragma-defined variables, you must follow these rules:
- Dual Declaration: Every variable must have both a
definepragma and aninitializepragma. - Scope:
definepragmas must be placed in the file scope.initializepragmas must be placed in the function scope (e.g., insidemain()).
- Vertex/Fragment Synchronization: If a variable is defined and initialized in the fragment shader, it must also be defined and initialized in the vertex shader. This is because
attributes are not directly accessible from the fragment shader and must be passed through via interpolation.
#pragma mapbox: define highp vec4 color main() { #pragma mapbox: initialize highp vec4 color // ... logic to set color ... gl_FragColor = color; }- Dual Declaration: Every variable must have both a
Understand the Mapbox GL Shader Prelude
mainThe Mapbox GL shader compiler automatically includes two prelude files in every shader you write. You do not need to manually include them, but you should be aware of their existence as they provide the base environment for your shaders.
_prelude.fragment.glsl: Automatically included in fragment shaders._prelude.vertex.glsl: Automatically included in vertex shaders.
How shader programs and data-driven properties are managed
mainMapbox GL JS uses a specialized system to handle data-driven styling within WebGL shaders. This is managed by the
PainterandProgramConfigurationclasses.Shader Compilation
ProgramConfigurationhandles the expansion of#pragma mapboxstatements in shader source code. It determines whether a style property should be treated as a:- Uniform: For constant values across a layer.
- Attribute, Varying, or Local variable: When the property is data-driven (varying per feature).
Data-Driven Paint Properties
For properties that change per feature (data-driven),
ProgramConfigurationcreates and populates a paint vertex array during the layout phase on the worker side. This array corresponds to theattributesdeclared in the shader, allowing the GPU to access unique values for every feature during the render pass.Filter syntax for Mapbox GL features
mainFilters are defined using nested arrays following the Mapbox GL JS specification. They allow for logical operations and property comparisons to target specific data within a layer.
Common logical operators include:
"all": Matches if all expressions are true."any": Matches if any expression is true."none": Matches if no expressions are true."in": Checks if a value exists within a provided list.
Comparison operators include
==,!=,<=,>=,<,>, etc. You can filter by feature properties or the special$typekey to check the geometry type.Develop @mapbox/mapbox-gl-pmtiles-provider
mainTo work on the provider locally, use the following commands to build the bundle and run the unit test suite.
npm run build # Build the bundle npm test # Run unit testsPublish @mapbox/mapbox-gl-pmtiles-provider to the CDN
mainTo publish a new version of the provider to the Mapbox CDN, follow these steps:
- Bump the
versioninpackage.json. - Update the default CDN URL in the Mapbox GL JS
TILE_PROVIDER_URLSconfiguration. - Build the project and run the publishing script.
Files are uploaded to
https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-pmtiles-provider/v{version}/mapbox-gl-pmtiles-provider.jswith immutable cache headers.npm run build ./publish_cdn.sh --dry-run # Preview commands ./publish_cdn.sh # Requires AWS credentials- Bump the
How to get started with Mapbox GL JS
mainTo use Mapbox GL JS, you must first sign up for a Mapbox account. The library is part of a larger ecosystem that includes native SDKs for Android, iOS, macOS, and React Native.
For practical implementation, refer to the following resources:
- Getting Started Guide: Overview
- Tutorials: Web App Tutorials
- API Reference: Full API Documentation
- Examples: Interactive Examples
Mapbox GL JS ESLint Configuration Overview
mainThe project uses a highly customized ESLint configuration designed for TypeScript and browser compatibility. It enforces strict JSDoc requirements for core files, manages specific import restrictions to ensure bundle compatibility (e.g., preventing
process.envorimport.meta.urlin UMD bundles), and includes custom Mapbox rules.Key configuration aspects include:
- Strict JSDoc: Enforced on core files like
src/index.tsandsrc/ui/**to ensure high-quality documentation. - Browser Compatibility: Rules are configured to prevent the use of Node.js-specific globals or syntax that would break browser bundles.
- TypeScript Integration: Uses
typescript-eslintwith type-checked rules. - Custom Rules: Includes
mapbox/devtools-must-use-debug-runandmapbox/no-object-methods-on-collections. - File-Specific Overrides: Different rules apply to
DEV_FILES,STRICT_JSDOC_FILES, andUNTYPED_FILESto balance strictness with developer velocity.
- Strict JSDoc: Enforced on core files like