Skip to content

Interaction

A Camera is a center and a zoom:

let mut cam = Camera::new(-77.0353, 38.8895, 14.0); // lon, lat, zoom
cam.pan_cells(10.0, 0.0); // ten columns east
cam.zoom_by(1.0, 20.0); // one level in, at most 20

Viewport::new(&cam, area) converts between lon/lat, world coordinates, dots and cells for a given area (dot_ll, dot_to_lonlat, cell_to_lonlat, km_per_col).

Controller owns a camera and turns crossterm events into MapLibre GL gestures:

let mut ctl = Controller::new(Camera::new(-77.0353, 38.8895, 13.0), 0.0, 17.0); // min, max zoom
loop {
ctl.tick(Instant::now()); // advance easing and inertia
ctl.set_area(map_area); // where the map is on screen
// ... draw with ctl.cam ...
match event::read()? {
Event::Key(k) => { ctl.key(k); }
Event::Mouse(m) => { ctl.mouse(m); }
_ => {}
}
}

key and mouse return true when they handled the event, so you can give other keys to the rest of your app. Poll for events at about 16 ms while ctl.animating(), and less often otherwise.

  • Wheel zooms toward the cursor; sideways wheel pans.
  • Drag pans, with inertia when released while moving.
  • Double-click zooms in, shift+double-click out.
  • Shift+drag draws a box and zooms to it (box_rect() gives the box to draw).
  • Arrows, hjkl and +/- are eased.
  • Right-click does nothing.
Method Like MapLibre’s
ease_to(camera) easeTo
fly_to(camera) flyTo: zoom out, travel, zoom back in; longer trips take longer
fit_bounds((w, s, e, n), max_zoom) fitBounds
ease_zoom(dz, (col, row)) Zoom around a cell
stop() Stop any animation
if let Some(click) = ctl.take_click() {
// click.lon, click.lat, and the terminal cell click.col, click.row
}

take_click only reports single clicks: drags, double-clicks and box zooms are gestures, not clicks. Pair a click with query_rendered_features to make features clickable.

ctl.pointer() is the last pointer position the controller saw, for hover effects. Events turns clicks and the pointer into layer events for you.