maplibre-rs
repository·main·Indexed 23 days ago
https://github.com/maplibre/maplibre-rsA portable and performant vector map rendering library written in Rust. It leverages WebGPU to target web, mobile, and desktop platforms (Linux, Android, iOS, macOS) with a single codebase. Key capabilities include rendering vector tile datasets, multithreading support, and feature data querying.
What's inside maplibre-rs
- maplibre-rs is a portable and performant vector maps renderer. It is designed to be used across different platforms as a core rendering engine for vector maps.
Overview of maplibre-rs capabilities
mainmaplibre-rs is a portable, high-performance vector map renderer written in Rust. It uses WebGPU to provide cross-platform support across Web, Mobile, and Desktop (Linux, Android, iOS, macOS).
Current Capabilities
- Rendering vector tile datasets.
- Simple navigation (powered by
winit). - Multithreading support on all platforms.
- Querying feature data.
Limitations & Missing Features
- Rendering: Does not yet support Text, Labels, Symbols, Raster data, 3D terrain, or Hill-shade (DEM).
- Data: No support for GeoJSON or per-feature rendering.
- Interoperability: No official APIs for TypeScript, Swift, or Java/Kotlin yet.
- Collision: Collision detection is not yet implemented.
Packaging maplibre-rs for the Web
mainWhen packaging
maplibre-rsas an npm package, several requirements must be met to ensure compatibility with modern web environments:- WASM Bundling: The WebAssembly binary must be accessible to users.
- WebWorker Bundling/Inlining: WebWorkers must be available, either as separate files or inlined as strings.
- Predictable Paths: Assets must be at predictable locations so users can reference them directly from
node_modulesif necessary. - ESM Support: The standard module format is preferred as it allows bundlers to resolve WebAssembly files and WebWorkers dynamically using
import.meta.url.
Resolving Assets in ESM
To resolve WebWorkers or WASM files in an ESM module, use the following syntax:
// Resolving a WebWorker new Worker(new URL("./multithreaded-pool.worker.ts", import.meta.url), { type: 'module' }); // Resolving a WASM file new URL('index_bg.wasm', import.meta.url);Understand maplibre-rs Apple packaging formats
mainOn Apple platforms,
maplibre-rsis distributed in three ways:- Multiple
.xcarchivepackages: Each package contains a framework for a specific architecture and platform. - A single
.xcframeworkpackage: A unified package containing multiple frameworks for different architectures and platforms. - A Swift Package: A wrapper that references the
.xcframeworkpackage to simplify distribution.
- Multiple
Use Single NativeActivity for Android applications
mainBecausewinitcurrently only supportsNativeActivity, applications usingmaplibre-rson Android must run in fullscreen mode. To use aNativeActivity, you must reference the name of your shared library in theAndroidManifest.xmlfile.Profile frames using the Tracy profiler
mainmaplibre-rs uses the Tracy profiler for frame profiling. The integration connects Tracy to the Rust
tracingcrate via therust_tracy_clientproject (comprisingtracing-tracy,tracy-client, andtracy-client-sys).Note that Tracy does not follow semantic versioning, so you must ensure the versions of the Rust client crates match the specific version of the Tracy binary you are running.
Understand font rendering approaches in maplibre-rs
mainBecause no single font rendering solution is perfect for all environments,
maplibre-rsconsiders several different architectural approaches. When choosing or implementing a rendering path, consider the following methods:- Tessellate Fonts: Converting glyphs into meshes (e.g., using tools like
ttf2mesh). This allows for high-performance rendering but requires generating geometry for glyphs. - SDF (Signed Distance Field) Font Rendering: Using Signed Distance Fields to represent glyphs. This is a common technique in map engines (like Mapbox GL) that allows for sharp text at various scales. Tools like
msdfgenare often used as a foundation. - GPU Text Rendering from Bezier Curves: Rendering text directly from vector data on the GPU. This provides high fidelity but is mathematically complex. Examples include implementations like
gllabelor the (patented) Slug library algorithm. - Web Canvas Rendering: Drawing text onto a Web Canvas and then uploading the resulting texture to the GPU. This is simpler but lacks the ability to dynamically scale fonts based on zoom levels without re-rendering.
- Tessellate Fonts: Converting glyphs into meshes (e.g., using tools like
How caching works in maplibre-rs
mainCaching in
maplibre-rsis implemented at the networking layer rather than through a custom serialization format. The library caches data in the same format as the original network requests. This approach allows the library to honor standard HTTP headers (such as expiry dates), which is critical for managing tile expiration.Caching behavior depends on the target platform:
- Web: Relies on the browser's native automatic caching of raw tiles.
- Linux, macOS, iOS, and Android: Utilizes the
reqwest-middleware-cachecrate to write raw network requests to disk.
Using maplibre-rs via IIFE (Script Tags)
mainThe IIFE (immediately-invoked function expression) format is used when including
maplibre-rsdirectly in a<script>tag for quick prototyping or playgrounds.In this mode, the library is attached to the
windoworglobalobject. Because there is no active bundler to manage assets, you must ensure that the WASM file and any non-inlined WebWorkers are deployed at a predictable path. Users may need to manually specify the location of these assets.Package an .xcframework
mainYou can create an
.xcframeworkby combining multiple frameworks usingxcodebuild.Note on Fat Binaries: You cannot bundle multiple architectures for the same platform (e.g., macOS-arm64 and macOS-x86_64) directly into an
.xcframework. For these cases, you must first create a fat binary usinglipo, then package the resulting framework.Steps for Fat Binaries:
- Create a fat binary:
lipo -create binA binB -output binfat - Copy the fat binary into a new framework and manually add the
.swiftmoduledefinitions from the original architectures.
xargs xcodebuild -create-xcframework -framework ./a -framework ./b -output out.xcframework- Create a fat binary:
Set up the Rust environment for maplibre-rs
mainThe project requires the Rust toolchain. It is recommended to installrustupto manage toolchains. The specific toolchain required by this project is defined in the./rust-toolchain.tomlfile and will be automatically downloaded when you build the project.Set up an Android Gradle project for maplibre-rs
mainTo package an Android
.aararchive for use withmaplibre-rs, use therust-android-gradleplugin. Note that some customizations may be required to support the latest NDK toolchain releases.https://github.com/mozilla/rust-android-gradle