Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

lonboard interop

manywidgets.lonboard ships control widgets for lonboard maps. They’re an optional subpackage:

pip install "manywidgets[lonboard]"

These are control-plane widgets — they reference a lonboard Map/layer and mutate its traits; they don’t render the map. They work in a live kernel and in static export (no kernel), resolving the layer through @manywidgets/core’s resolveModel and fanning each write out to every proxy of the layer (the Map keeps its own).

Widgets

Compose them with the layout widgets to put a control panel beside the map:

from manywidgets import Column
from manywidgets.lonboard import LayerToggle, FilterBinder

Column(LayerToggle(layer), FilterBinder(slider, layer), m)

Recipe: a layer switcher

A Map can hold several layers; one LayerToggle per layer (in a Column) is a layer switcher. Works for any layer type — vector or raster (BitmapTileLayer):

from lonboard import Map, BitmapTileLayer
from manywidgets import Column
from manywidgets.lonboard import LayerToggle

osm = BitmapTileLayer(data="https://tile.openstreetmap.org/{z}/{x}/{y}.png", visible=True)
topo = BitmapTileLayer(data="https://a.tile.opentopomap.org/{z}/{x}/{y}.png", visible=False)
m = Map([osm, topo], basemap=None)

Column(
    Column(LayerToggle(osm, label="OpenStreetMap"), LayerToggle(topo, label="OpenTopoMap")),
    m,
)

See it live in the interop example.

Recipe: data-driven styling + legend

Colour a layer by a data attribute with a per-row get_fill_color array, and pair it with a Legend built from the same palette:

import numpy as np
from manywidgets import Legend

palette = np.array([[230, 30, 30], [30, 160, 30], [30, 90, 230]], dtype="uint8")
layer = ScatterplotLayer.from_geopandas(gdf, get_fill_color=palette[categories])  # one colour per row
legend = Legend([[palette[i].tolist(), name] for i, name in enumerate(["A", "B", "C"])], title="Category")

(For binned continuous data, bin the values and label the ranges, e.g. ["0–10", "10–20", …].) See the interop example.

Recipe: fly to preset locations

MapFlyer repositions an already-rendered Map — something Map.view_state can’t do (it’s uncontrolled: deck.gl reads it once as initialViewState). Each preset is a dict with a label and camera keys; clicking a button animates the map there:

from lonboard import Map
from manywidgets import Column
from manywidgets.lonboard import MapFlyer

m = Map(layer)
flyer = MapFlyer(m, locations=[
    {"label": "New York", "longitude": -74.0, "latitude": 40.7, "zoom": 10},
    {"label": "London", "longitude": -0.12, "latitude": 51.5, "zoom": 9},
], duration=3000)

Column(flyer, m)

It drives lonboard’s existing fly_to (a deck.gl FlyToInterpolator animation) from the browser — no kernel needed — so it works the same live and in static export.

Caveats

See the interop example for a working map.