pub struct Map {
pub raster_mode: RasterMode,
pub center: Option<(f64, f64, f64)>,
pub retry: RetryPolicy,
/* private fields */
}Expand description
A map: sources, style and custom layers, feature state, and how raster layers draw. See the module docs.
Fields§
§raster_mode: RasterModeHow raster layers draw (cell colors unless set to kitty images).
center: Option<(f64, f64, f64)>The starting view (lon, lat, zoom) a style suggests.
retry: RetryPolicyWhen to ask again for tiles that failed to load.
Implementations§
Source§impl Map
impl Map
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty map.
Examples found in repository?
14async fn main() -> anyhow::Result<()> {
15 let mut map = Map::new();
16 map.add_source("omt", MapSource::vector(Source::open(mapterm::source::OPENFREEMAP).await?))?;
17 map.add_source("pin", MapSource::geojson(&json!({"type": "Feature", "id": 1, "properties": {"name": "Washington Monument"},
18 "geometry": {"type": "Point", "coordinates": [-77.0353, 38.8895]}}))?)?;
19 map.add_layer(StyleLayer::background("bg").color("#101418"))?;
20 map.add_layer(StyleLayer::fill("park", "omt").source_layer("park").color("#1a3220"))?;
21 map.add_layer(StyleLayer::fill("water", "omt").source_layer("water").color("#16304a"))?;
22 map.add_layer(StyleLayer::line("roads", "omt").source_layer("transportation").color(json!(
23 ["match", ["get", "class"], "motorway", "#eb6e3c", "trunk", "#e1a046", "primary", "#d2c36e", "#5a5a5a"])))?;
24 map.add_layer(StyleLayer::symbol("places", "omt").source_layer("place").text(json!(["get", "name"]))
25 .sort_key(json!(["get", "rank"])).color("#e1e1e1"))?;
26 map.add_layer(StyleLayer::symbol("pin", "pin").glyph("◆").text("{name}")
27 .color(json!(["case", ["boolean", ["feature-state", "hover"], false], "yellow", "cyan"])))?;
28 let mut events = Events::new(&["pin", "places"]).hover_state("hover");
29
30 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
31 let mut status = String::new();
32 let mut term = ratatui::init();
33 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
34 loop {
35 ctl.tick(Instant::now());
36 let area = term.get_frame().area();
37 ctl.set_area(area);
38 let _ = map.load_tiles(&ctl.cam, area).await; // a real app loads in the background
39 term.draw(|f| {
40 f.render_widget(map.view(&ctl.cam), area);
41 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
42 })?;
43 events.pointer(&mut map, &ctl.cam, area, ctl.pointer()); // hover: the pin turns yellow
44 if let Some(click) = ctl.take_click() {
45 for e in events.click(&map, &ctl.cam, area, &click) {
46 if let MapEvent::Click { layer, features, .. } = e {
47 status = format!("{layer}: {}", features[0].title());
48 }
49 }
50 }
51 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
52 match event::read()? {
53 Event::Key(k) if k.code == KeyCode::Char('q') => break,
54 Event::Key(k) => _ = ctl.key(k),
55 Event::Mouse(m) => _ = ctl.mouse(m),
56 _ => {}
57 }
58 }
59 }
60 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
61 ratatui::restore();
62 Ok(())
63}Sourcepub fn add_source(
&mut self,
id: impl Into<String>,
src: MapSource,
) -> Result<()>
pub fn add_source( &mut self, id: impl Into<String>, src: MapSource, ) -> Result<()>
Add a source under id (an error if the id is taken).
Examples found in repository?
14async fn main() -> anyhow::Result<()> {
15 let mut map = Map::new();
16 map.add_source("omt", MapSource::vector(Source::open(mapterm::source::OPENFREEMAP).await?))?;
17 map.add_source("pin", MapSource::geojson(&json!({"type": "Feature", "id": 1, "properties": {"name": "Washington Monument"},
18 "geometry": {"type": "Point", "coordinates": [-77.0353, 38.8895]}}))?)?;
19 map.add_layer(StyleLayer::background("bg").color("#101418"))?;
20 map.add_layer(StyleLayer::fill("park", "omt").source_layer("park").color("#1a3220"))?;
21 map.add_layer(StyleLayer::fill("water", "omt").source_layer("water").color("#16304a"))?;
22 map.add_layer(StyleLayer::line("roads", "omt").source_layer("transportation").color(json!(
23 ["match", ["get", "class"], "motorway", "#eb6e3c", "trunk", "#e1a046", "primary", "#d2c36e", "#5a5a5a"])))?;
24 map.add_layer(StyleLayer::symbol("places", "omt").source_layer("place").text(json!(["get", "name"]))
25 .sort_key(json!(["get", "rank"])).color("#e1e1e1"))?;
26 map.add_layer(StyleLayer::symbol("pin", "pin").glyph("◆").text("{name}")
27 .color(json!(["case", ["boolean", ["feature-state", "hover"], false], "yellow", "cyan"])))?;
28 let mut events = Events::new(&["pin", "places"]).hover_state("hover");
29
30 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
31 let mut status = String::new();
32 let mut term = ratatui::init();
33 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
34 loop {
35 ctl.tick(Instant::now());
36 let area = term.get_frame().area();
37 ctl.set_area(area);
38 let _ = map.load_tiles(&ctl.cam, area).await; // a real app loads in the background
39 term.draw(|f| {
40 f.render_widget(map.view(&ctl.cam), area);
41 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
42 })?;
43 events.pointer(&mut map, &ctl.cam, area, ctl.pointer()); // hover: the pin turns yellow
44 if let Some(click) = ctl.take_click() {
45 for e in events.click(&map, &ctl.cam, area, &click) {
46 if let MapEvent::Click { layer, features, .. } = e {
47 status = format!("{layer}: {}", features[0].title());
48 }
49 }
50 }
51 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
52 match event::read()? {
53 Event::Key(k) if k.code == KeyCode::Char('q') => break,
54 Event::Key(k) => _ = ctl.key(k),
55 Event::Mouse(m) => _ = ctl.mouse(m),
56 _ => {}
57 }
58 }
59 }
60 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
61 ratatui::restore();
62 Ok(())
63}Sourcepub fn add_map(
&mut self,
other: Map,
before: Option<&str>,
) -> Result<Vec<String>>
pub fn add_map( &mut self, other: Map, before: Option<&str>, ) -> Result<Vec<String>>
Move another map’s sources and layers into this one, its layers just below before
(or on top): e.g. a style loaded with Map::from_style on another task, swapped in
under your own layers. Returns the ids of the layers added. Nothing changes if a source
or layer id is already taken.
Sourcepub fn remove_source(&mut self, id: &str) -> bool
pub fn remove_source(&mut self, id: &str) -> bool
Remove a source; layers that use it stay but draw nothing.
Sourcepub fn sources(&self) -> impl Iterator<Item = (&str, &MapSource)>
pub fn sources(&self) -> impl Iterator<Item = (&str, &MapSource)>
Every source with its id, in the order added.
Sourcepub fn set_attribution(&mut self, id: &str, text: &str) -> Result<()>
pub fn set_attribution(&mut self, id: &str, text: &str) -> Result<()>
Set a source’s credit (plain text, or HTML that crate::source::plain_attribution
turns into text); empty removes it. Raster sources keep theirs on the shared source.
Sourcepub fn set_feature_state(
&mut self,
source: &str,
id: &Value,
state: &Json,
) -> Result<()>
pub fn set_feature_state( &mut self, source: &str, id: &Value, state: &Json, ) -> Result<()>
Set feature state (MapLibre’s setFeatureState): the keys of state (a JSON object)
are merged into the feature’s state, which paint expressions read with
["feature-state", key]. id is the feature’s id, or its promoteId property.
Sourcepub fn remove_feature_state(
&mut self,
source: &str,
id: Option<&Value>,
key: Option<&str>,
)
pub fn remove_feature_state( &mut self, source: &str, id: Option<&Value>, key: Option<&str>, )
Remove feature state: one key of one feature, all of one feature’s state, or (with no id) all state of the source.
Sourcepub fn feature_state(&self, source: &str, id: &Value) -> Json
pub fn feature_state(&self, source: &str, id: &Value) -> Json
A feature’s state as a JSON object (empty when none is set).
Sourcepub fn attributions(&self, zoom: f64) -> Vec<String>
pub fn attributions(&self, zoom: f64) -> Vec<String>
The credits of the sources that the layers shown at zoom draw from, in source order
and without repeats, as MapLibre’s attribution control lists them.
Sourcepub fn cluster_expansion_zoom(
&self,
source: &str,
cluster_id: u64,
) -> Option<f64>
pub fn cluster_expansion_zoom( &self, source: &str, cluster_id: u64, ) -> Option<f64>
The zoom at which a cluster of a clustered GeoJSON source splits into its parts
(MapLibre’s getClusterExpansionZoom): fly there when a cluster is clicked.
Sourcepub fn set_data(&mut self, id: &str, doc: &Json) -> Result<()>
pub fn set_data(&mut self, id: &str, doc: &Json) -> Result<()>
Replace a GeoJSON source’s data (MapLibre’s setData).
Sourcepub fn source_bounds(&self, id: &str) -> Option<(f64, f64, f64, f64)>
pub fn source_bounds(&self, id: &str) -> Option<(f64, f64, f64, f64)>
Lon/lat bounds (west, south, east, north) of a GeoJSON source, for fitting the view.
Sourcepub fn tile_requests(&self, cam: &Camera, area: Rect) -> Vec<TileRequest>
pub fn tile_requests(&self, cam: &Camera, area: Rect) -> Vec<TileRequest>
Tiles the view needs that aren’t loaded yet, for sources that shown layers use and the
map can fetch itself (vector sources from MapSource::vector, raster sources).
Sourcepub fn insert_loaded(
&mut self,
source: &str,
id: TileId,
loaded: Result<Loaded>,
) -> Result<()>
pub fn insert_loaded( &mut self, source: &str, id: TileId, loaded: Result<Loaded>, ) -> Result<()>
Store a tile loaded with TileRequest::load. A failed load returns its error and the
tile is requested again after a growing wait (Map::retry); after the last attempt
it is stored empty. Lower-zoom tiles stand in until then.
Sourcepub async fn load_tiles(&mut self, cam: &Camera, area: Rect) -> Result<()>
pub async fn load_tiles(&mut self, cam: &Camera, area: Rect) -> Result<()>
Fetch the missing tiles one at a time (simple apps; see Map::tile_requests to load
in the background). Failed tiles are retried later (see Map::retry) and the first
error is returned.
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}More examples
14async fn main() -> anyhow::Result<()> {
15 let mut map = Map::new();
16 map.add_source("omt", MapSource::vector(Source::open(mapterm::source::OPENFREEMAP).await?))?;
17 map.add_source("pin", MapSource::geojson(&json!({"type": "Feature", "id": 1, "properties": {"name": "Washington Monument"},
18 "geometry": {"type": "Point", "coordinates": [-77.0353, 38.8895]}}))?)?;
19 map.add_layer(StyleLayer::background("bg").color("#101418"))?;
20 map.add_layer(StyleLayer::fill("park", "omt").source_layer("park").color("#1a3220"))?;
21 map.add_layer(StyleLayer::fill("water", "omt").source_layer("water").color("#16304a"))?;
22 map.add_layer(StyleLayer::line("roads", "omt").source_layer("transportation").color(json!(
23 ["match", ["get", "class"], "motorway", "#eb6e3c", "trunk", "#e1a046", "primary", "#d2c36e", "#5a5a5a"])))?;
24 map.add_layer(StyleLayer::symbol("places", "omt").source_layer("place").text(json!(["get", "name"]))
25 .sort_key(json!(["get", "rank"])).color("#e1e1e1"))?;
26 map.add_layer(StyleLayer::symbol("pin", "pin").glyph("◆").text("{name}")
27 .color(json!(["case", ["boolean", ["feature-state", "hover"], false], "yellow", "cyan"])))?;
28 let mut events = Events::new(&["pin", "places"]).hover_state("hover");
29
30 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
31 let mut status = String::new();
32 let mut term = ratatui::init();
33 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
34 loop {
35 ctl.tick(Instant::now());
36 let area = term.get_frame().area();
37 ctl.set_area(area);
38 let _ = map.load_tiles(&ctl.cam, area).await; // a real app loads in the background
39 term.draw(|f| {
40 f.render_widget(map.view(&ctl.cam), area);
41 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
42 })?;
43 events.pointer(&mut map, &ctl.cam, area, ctl.pointer()); // hover: the pin turns yellow
44 if let Some(click) = ctl.take_click() {
45 for e in events.click(&map, &ctl.cam, area, &click) {
46 if let MapEvent::Click { layer, features, .. } = e {
47 status = format!("{layer}: {}", features[0].title());
48 }
49 }
50 }
51 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
52 match event::read()? {
53 Event::Key(k) if k.code == KeyCode::Char('q') => break,
54 Event::Key(k) => _ = ctl.key(k),
55 Event::Mouse(m) => _ = ctl.mouse(m),
56 _ => {}
57 }
58 }
59 }
60 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
61 ratatui::restore();
62 Ok(())
63}Sourcepub fn zoom_range(&self) -> (u8, u8)
pub fn zoom_range(&self) -> (u8, u8)
The zoom range of the vector sources (min of minimums, max of maximums).
Sourcepub fn kitty_commands(
&mut self,
cam: &Camera,
area: Rect,
state: &mut KittyState,
) -> String
pub fn kitty_commands( &mut self, cam: &Camera, area: Rect, state: &mut KittyState, ) -> String
Kitty graphics commands that place the shown raster layers under the text for this
frame (images are sent once, then only moved). Write them after the frame’s cells, in
the same synchronized update. Empty unless Map::raster_mode is kitty.
Sourcepub fn insert_tile(
&mut self,
source: &str,
id: TileId,
bytes: Option<&[u8]>,
) -> Result<()>
pub fn insert_tile( &mut self, source: &str, id: TileId, bytes: Option<&[u8]>, ) -> Result<()>
Add a vector tile (MVT bytes, or None for an empty tile) to a vector source.
Sourcepub fn add_layer(&mut self, layer: StyleLayer) -> Result<()>
pub fn add_layer(&mut self, layer: StyleLayer) -> Result<()>
Add a style layer on top.
Examples found in repository?
14async fn main() -> anyhow::Result<()> {
15 let mut map = Map::new();
16 map.add_source("omt", MapSource::vector(Source::open(mapterm::source::OPENFREEMAP).await?))?;
17 map.add_source("pin", MapSource::geojson(&json!({"type": "Feature", "id": 1, "properties": {"name": "Washington Monument"},
18 "geometry": {"type": "Point", "coordinates": [-77.0353, 38.8895]}}))?)?;
19 map.add_layer(StyleLayer::background("bg").color("#101418"))?;
20 map.add_layer(StyleLayer::fill("park", "omt").source_layer("park").color("#1a3220"))?;
21 map.add_layer(StyleLayer::fill("water", "omt").source_layer("water").color("#16304a"))?;
22 map.add_layer(StyleLayer::line("roads", "omt").source_layer("transportation").color(json!(
23 ["match", ["get", "class"], "motorway", "#eb6e3c", "trunk", "#e1a046", "primary", "#d2c36e", "#5a5a5a"])))?;
24 map.add_layer(StyleLayer::symbol("places", "omt").source_layer("place").text(json!(["get", "name"]))
25 .sort_key(json!(["get", "rank"])).color("#e1e1e1"))?;
26 map.add_layer(StyleLayer::symbol("pin", "pin").glyph("◆").text("{name}")
27 .color(json!(["case", ["boolean", ["feature-state", "hover"], false], "yellow", "cyan"])))?;
28 let mut events = Events::new(&["pin", "places"]).hover_state("hover");
29
30 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
31 let mut status = String::new();
32 let mut term = ratatui::init();
33 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
34 loop {
35 ctl.tick(Instant::now());
36 let area = term.get_frame().area();
37 ctl.set_area(area);
38 let _ = map.load_tiles(&ctl.cam, area).await; // a real app loads in the background
39 term.draw(|f| {
40 f.render_widget(map.view(&ctl.cam), area);
41 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
42 })?;
43 events.pointer(&mut map, &ctl.cam, area, ctl.pointer()); // hover: the pin turns yellow
44 if let Some(click) = ctl.take_click() {
45 for e in events.click(&map, &ctl.cam, area, &click) {
46 if let MapEvent::Click { layer, features, .. } = e {
47 status = format!("{layer}: {}", features[0].title());
48 }
49 }
50 }
51 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
52 match event::read()? {
53 Event::Key(k) if k.code == KeyCode::Char('q') => break,
54 Event::Key(k) => _ = ctl.key(k),
55 Event::Mouse(m) => _ = ctl.mouse(m),
56 _ => {}
57 }
58 }
59 }
60 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
61 ratatui::restore();
62 Ok(())
63}Sourcepub fn add_layer_before(
&mut self,
layer: StyleLayer,
before: &str,
) -> Result<()>
pub fn add_layer_before( &mut self, layer: StyleLayer, before: &str, ) -> Result<()>
Add a style layer just below before.
Sourcepub fn add_custom_layer<T: CustomLayer + Any + Send>(
&mut self,
id: impl Into<String>,
layer: T,
before: Option<&str>,
) -> Result<()>
pub fn add_custom_layer<T: CustomLayer + Any + Send>( &mut self, id: impl Into<String>, layer: T, before: Option<&str>, ) -> Result<()>
Add a custom layer (see CustomLayer) on top, or below before.
Sourcepub fn add_layers(
&mut self,
layers: Vec<StyleLayer>,
before: Option<&str>,
) -> Result<()>
pub fn add_layers( &mut self, layers: Vec<StyleLayer>, before: Option<&str>, ) -> Result<()>
Add several style layers at once (on top, or below before), restyling loaded tiles
only once. Nothing is added if any id is taken.
Sourcepub fn remove_layers(&mut self, ids: &[&str]) -> usize
pub fn remove_layers(&mut self, ids: &[&str]) -> usize
Remove several layers at once, restyling only once. Returns how many were removed.
Sourcepub fn remove_layer(&mut self, id: &str) -> bool
pub fn remove_layer(&mut self, id: &str) -> bool
Remove a layer; false if there was none.
Sourcepub fn move_layer(&mut self, id: &str, before: Option<&str>) -> Result<()>
pub fn move_layer(&mut self, id: &str, before: Option<&str>) -> Result<()>
Move a layer below before, or to the top.
Sourcepub fn layer_ids(&self) -> Vec<&str>
pub fn layer_ids(&self) -> Vec<&str>
Layer ids, bottom first.
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}Sourcepub fn layer(&self, id: &str) -> Option<&StyleLayer>
pub fn layer(&self, id: &str) -> Option<&StyleLayer>
A style layer by id (None for custom layers).
Sourcepub fn custom_layer_mut<T: CustomLayer + Any + Send>(
&mut self,
id: &str,
) -> Option<&mut T>
pub fn custom_layer_mut<T: CustomLayer + Any + Send>( &mut self, id: &str, ) -> Option<&mut T>
A custom layer by id and type, to change its state.
Sourcepub fn set_paint(&mut self, id: &str, name: &str, v: &Json) -> Result<()>
pub fn set_paint(&mut self, id: &str, name: &str, v: &Json) -> Result<()>
Set a paint property of a style layer (MapLibre’s setPaintProperty).
Sourcepub fn set_layout(&mut self, id: &str, name: &str, v: &Json) -> Result<()>
pub fn set_layout(&mut self, id: &str, name: &str, v: &Json) -> Result<()>
Set a layout property of a style layer (MapLibre’s setLayoutProperty).
Sourcepub fn set_filter(&mut self, id: &str, f: Option<&Json>) -> Result<()>
pub fn set_filter(&mut self, id: &str, f: Option<&Json>) -> Result<()>
Replace a layer’s filter (None draws every feature).
Sourcepub fn set_zoom_range(&mut self, id: &str, min: f64, max: f64) -> Result<()>
pub fn set_zoom_range(&mut self, id: &str, min: f64, max: f64) -> Result<()>
Draw a layer only from min up to (not including) max zoom.
Sourcepub fn warnings(&self) -> &[String]
pub fn warnings(&self) -> &[String]
Problems met while building the style (unsupported expressions and the like).
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}Sourcepub fn view<'a>(&'a self, camera: &'a Camera) -> MapView<'a>
pub fn view<'a>(&'a self, camera: &'a Camera) -> MapView<'a>
A widget that draws the map with this camera.
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}More examples
14async fn main() -> anyhow::Result<()> {
15 let mut map = Map::new();
16 map.add_source("omt", MapSource::vector(Source::open(mapterm::source::OPENFREEMAP).await?))?;
17 map.add_source("pin", MapSource::geojson(&json!({"type": "Feature", "id": 1, "properties": {"name": "Washington Monument"},
18 "geometry": {"type": "Point", "coordinates": [-77.0353, 38.8895]}}))?)?;
19 map.add_layer(StyleLayer::background("bg").color("#101418"))?;
20 map.add_layer(StyleLayer::fill("park", "omt").source_layer("park").color("#1a3220"))?;
21 map.add_layer(StyleLayer::fill("water", "omt").source_layer("water").color("#16304a"))?;
22 map.add_layer(StyleLayer::line("roads", "omt").source_layer("transportation").color(json!(
23 ["match", ["get", "class"], "motorway", "#eb6e3c", "trunk", "#e1a046", "primary", "#d2c36e", "#5a5a5a"])))?;
24 map.add_layer(StyleLayer::symbol("places", "omt").source_layer("place").text(json!(["get", "name"]))
25 .sort_key(json!(["get", "rank"])).color("#e1e1e1"))?;
26 map.add_layer(StyleLayer::symbol("pin", "pin").glyph("◆").text("{name}")
27 .color(json!(["case", ["boolean", ["feature-state", "hover"], false], "yellow", "cyan"])))?;
28 let mut events = Events::new(&["pin", "places"]).hover_state("hover");
29
30 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
31 let mut status = String::new();
32 let mut term = ratatui::init();
33 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
34 loop {
35 ctl.tick(Instant::now());
36 let area = term.get_frame().area();
37 ctl.set_area(area);
38 let _ = map.load_tiles(&ctl.cam, area).await; // a real app loads in the background
39 term.draw(|f| {
40 f.render_widget(map.view(&ctl.cam), area);
41 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
42 })?;
43 events.pointer(&mut map, &ctl.cam, area, ctl.pointer()); // hover: the pin turns yellow
44 if let Some(click) = ctl.take_click() {
45 for e in events.click(&map, &ctl.cam, area, &click) {
46 if let MapEvent::Click { layer, features, .. } = e {
47 status = format!("{layer}: {}", features[0].title());
48 }
49 }
50 }
51 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
52 match event::read()? {
53 Event::Key(k) if k.code == KeyCode::Char('q') => break,
54 Event::Key(k) => _ = ctl.key(k),
55 Event::Mouse(m) => _ = ctl.mouse(m),
56 _ => {}
57 }
58 }
59 }
60 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
61 ratatui::restore();
62 Ok(())
63}Sourcepub fn query_rendered_features(
&self,
cam: &Camera,
area: Rect,
target: (f64, f64),
layers: Option<&[&str]>,
) -> Vec<Pick>
pub fn query_rendered_features( &self, cam: &Camera, area: Rect, target: (f64, f64), layers: Option<&[&str]>, ) -> Vec<Pick>
Features drawn under target (braille dots relative to area: 2 per column, 4 per
row), top layer first and, within a layer, points before lines before polygons.
layers limits the search to those layer ids. Custom layers answer with their pick.
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}Sourcepub fn query_features(
&self,
cam: &Camera,
area: Rect,
target: (f64, f64),
) -> Vec<Pick>
pub fn query_features( &self, cam: &Camera, area: Rect, target: (f64, f64), ) -> Vec<Pick>
Every feature of every source under target (dots relative to area), drawn or not,
for inspecting data. Sources come in the order of their topmost layer, top first;
within a source, points, then lines, then polygons from smallest to largest. Each pick’s
style_layer is the top shown layer that draws it, and drawn says whether one does.
Source§impl Map
impl Map
Sourcepub async fn from_style(spec: &str) -> Result<Map>
pub async fn from_style(spec: &str) -> Result<Map>
A map from a style: mapterm-dark or mapterm-light (the built-in terminal styles
over OpenFreeMap), an OpenFreeMap name (OPENFREEMAP_STYLES), a URL or a file.
Examples found in repository?
12async fn main() -> anyhow::Result<()> {
13 let spec = std::env::args().nth(1).unwrap_or_else(|| "liberty".into());
14 let mut map = Map::from_style(&spec).await?;
15 for w in map.warnings() {
16 eprintln!("warning: {w}");
17 }
18 let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0);
19 let mut status = format!("{spec}: {} layers", map.layer_ids().len());
20 let mut term = ratatui::init();
21 crossterm::execute!(std::io::stdout(), event::EnableMouseCapture)?;
22 loop {
23 ctl.tick(Instant::now());
24 let area = term.get_frame().area();
25 ctl.set_area(area);
26 let _ = map.load_tiles(&ctl.cam, area).await;
27 term.draw(|f| {
28 f.render_widget(map.view(&ctl.cam), area);
29 f.render_widget(ratatui::text::Line::from(status.as_str()), area);
30 })?;
31 if let Some(click) = ctl.take_click() {
32 let dot = Viewport::new(&ctl.cam, area).dot_ll(click.lon, click.lat);
33 let hits = map.query_rendered_features(&ctl.cam, area, dot, None);
34 let names: Vec<String> = hits.iter().take(4).map(|p| format!("{}: {}", p.style_layer.as_deref().unwrap_or("?"), p.title())).collect();
35 status = names.join(" | ");
36 }
37 if event::poll(Duration::from_millis(if ctl.animating() { 16 } else { 250 }))? {
38 match event::read()? {
39 Event::Key(k) if k.code == KeyCode::Char('q') => break,
40 Event::Key(k) => _ = ctl.key(k),
41 Event::Mouse(m) => _ = ctl.mouse(m),
42 _ => {}
43 }
44 }
45 }
46 crossterm::execute!(std::io::stdout(), event::DisableMouseCapture)?;
47 ratatui::restore();
48 Ok(())
49}Sourcepub fn terminal(src: Source, schema: Schema, dark: bool) -> Result<Map>
pub fn terminal(src: Source, schema: Schema, dark: bool) -> Result<Map>
A map drawing src with the built-in terminal style for its schema.
Sourcepub async fn from_style_json(doc: &Json) -> Result<Map>
pub async fn from_style_json(doc: &Json) -> Result<Map>
A map from a parsed style document. Vector sources that fail to open are errors; source types mapterm can’t draw yet (raster, raster-dem, image, video) become warnings.
Sourcepub fn add_style_layers(&mut self, doc: &Json) -> Result<()>
pub fn add_style_layers(&mut self, doc: &Json) -> Result<()>
Add a style document’s layers on top of the current ones.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for Map
impl !Sync for Map
impl !UnwindSafe for Map
impl Freeze for Map
impl Send for Map
impl Unpin for Map
impl UnsafeUnpin for Map
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more