Map and sources
A Map holds named sources (where the data comes from) and an ordered list
of layers (how to draw it), like a MapLibre map.
Creating a map
Section titled “Creating a map”// From a MapLibre style: an OpenFreeMap name, a URL, or a style.json file.let map = Map::from_style("positron").await?;let map = Map::from_style("https://example.com/style.json").await?;let map = Map::from_style("./style.json").await?;
// mapterm's built-in terminal styles.let map = Map::from_style("mapterm-dark").await?;
// From a style document you already have.let map = Map::from_style_json(&doc).await?;
// Empty: add sources and layers yourself.let mut map = Map::new();Map::from_style opens the style’s vector sources. If the style suggests a
starting view, it’s in map.center as (lon, lat, zoom).
Styles can use expressions or properties mapterm doesn’t support. Those are
skipped rather than guessed at, and listed in map.warnings().
To use the built-in style with a source of your own, detect the schema and
build it with Map::terminal:
use mapterm::stylejson::Schema;let src = Source::open("dc.pmtiles").await?;let map = Map::terminal(src, Schema::OpenMapTiles, true)?; // dark = trueSources
Section titled “Sources”// Vector tiles: PMTiles file or URL, XYZ template, or TileJSON.let src = Source::open("https://tiles.openfreemap.org/planet").await?;map.add_source("omt", MapSource::vector(src))?;
// GeoJSON: a FeatureCollection, a Feature or a bare geometry.map.add_source("sites", MapSource::geojson(&doc)?)?;
// Raster image tiles (see the raster module).let r = mapterm::raster::RasterSource::new("https://tile.openstreetmap.org/{z}/{x}/{y}.png", false, 19)?;map.add_source("osm", MapSource::raster(std::sync::Arc::new(r)))?;Source ids must be unique; add_source fails otherwise.
Clustering
Section titled “Clustering”GeoJSON sources are spatially indexed, so drawing and queries only touch
features near the view. Clustering works like MapLibre’s cluster: true:
use mapterm::cluster::ClusterOptions;
let src = MapSource::geojson(&points)?.with_cluster(ClusterOptions { radius_px: 50.0, max_zoom: 14 });map.add_source("stops", src)?;Up to max_zoom, nearby points become cluster features with cluster,
cluster_id, point_count and point_count_abbreviated properties; style them
with filters such as ["has", "point_count"]. When one is clicked,
map.cluster_expansion_zoom("stops", cluster_id) says where it splits, ready
for fly_to. In style JSON, cluster, clusterRadius and clusterMaxZoom
do the same, and set_data keeps clustering on.
Feature ids
Section titled “Feature ids”MapSource::geojson(&doc)?.with_promote_id("code") uses a property as the
feature id (MapLibre’s promoteId), for feature state.
GeoJSON ids and vector tile ids are used otherwise.
Other source methods
Section titled “Other source methods”| Method | Does |
|---|---|
source(id), sources() |
Look sources up |
remove_source(id) |
Remove one |
set_data(id, &doc) |
Replace a GeoJSON source’s data, like MapLibre’s setData |
source_bounds(id) |
A GeoJSON source’s lon/lat bounds, for fitting the view |
zoom_range() |
The zoom range of the vector sources |
Credits
Section titled “Credits”Sources carry their attribution: TileJSON and PMTiles metadata, a style
source’s attribution, or an imagery provider’s credit.
map.attributions(zoom) lists the credits of the sources that layers shown at
that zoom draw from, like MapLibre’s attribution control, and
set_attribution(id, text) changes one.
Layers
Section titled “Layers”Layers draw bottom to top in the order they’re added.
map.add_layer(StyleLayer::line("route", "trip").color("#00e5ff"))?;map.add_layer_before(StyleLayer::fill("zones", "zones").color("#202838"), "roads")?;map.add_layers(layers, Some("labels"))?; // several, below "labels"map.add_custom_layer("vehicles", my_layer, None)?; // a CustomLayer, on topChange them at runtime, as in MapLibre:
| Method | Does |
|---|---|
set_paint(id, "line-color", &json!("#f00")) |
Change a paint property |
set_layout(id, "text-field", &json!(["get", "ref"])) |
Change a layout property |
set_filter(id, Some(&json!(["==", ["get", "class"], "park"]))) |
Change or clear (None) the filter |
set_visibility(id, false) |
Hide or show |
set_zoom_range(id, 10.0, 24.0) |
Change min and max zoom |
move_layer(id, Some("labels")) |
Move below another layer, or to the top with None |
remove_layer(id), remove_layers(&[...]) |
Remove |
layer_ids(), layer(id) |
Inspect the stack |
custom_layer_mut::<T>(id) |
Get your custom layer back to update it |
Changes apply to loaded tiles at once; there’s nothing to refresh.
Combining maps
Section titled “Combining maps”map.add_map(other, before) moves another map’s sources and layers in, below
the layer before (or on top). The viewer uses it to switch basemap styles:
it loads the new style on a separate task (Map is Send), then swaps only the
basemap’s layers, keeping imagery underneath and data layers on top.
Feature state
Section titled “Feature state”set_feature_state, remove_feature_state and feature_state work as in
MapLibre; see Events and feature state.
Drawing
Section titled “Drawing”frame.render_widget(map.view(&camera), area);MapView is a ratatui Widget. It draws whatever tiles are loaded, using
lower-zoom tiles in place of ones that haven’t arrived yet.