Skip to content

Shiny

Input and output

Use output_maplibregl in the UI and render_maplibregl in the server section of your Shiny for Python app:

from shiny import App, ui
from maplibre import output_maplibregl, render_maplibregl, Map

app_ui = ui.page_fluid(
    ui.panel_title("MapLibre"),
    output_maplibregl("maplibre", height=600)
)


def server(input, output, session):
    @render_maplibregl
    def maplibre():
        m = Map()
        return m


app = App(app_ui, server)

Reactivity

Input events

MapLibre for Python provides the following reactive inputs:

  • map-on-click event: Sends the coordinates of the location that was clicked on. The name of the input event corresponds to the output id. For output_maplibregl("maplibre") you need to listen to input.maplibre.
  • feature-on-click event: Sends the properties of the feature that was clicked on. The name of the ìnput is made up of the output id + layer + layer id. For output_maplibregl("maplibre") and a layer with id=test you need to listen to input.maplibre_layer_test.

Map updates

Use MapContext to update your Map object.

Example

from maplibre import (
    Layer,
    LayerType,
    Map,
    MapContext,
    output_maplibregl,
    render_maplibregl,
)
from maplibre.sources import GeoJSONSource
from shiny import App, reactive, render, ui

LAYER_ID = "earthquakes"
CIRCLE_RADIUS = 5

app_ui = ui.page_fluid(
    #
    # Render map
    #
    ui.panel_title("MapLibre"),
    output_maplibregl("maplibre", height=600),
    #
    # Show coords
    #
    ui.div("Click on the map to print the coords.", style="padding: 10px;"),
    ui.output_text_verbatim("coords", placeholder=True),
    #
    # Show props of a feature
    #
    ui.div("Click on a feature to print its props.", style="padding: 10px;"),
    ui.output_text_verbatim("props", placeholder=True),
    #
    # Change radius
    #
    ui.input_slider("radius", "Radius", value=CIRCLE_RADIUS, min=1, max=10),
)


def server(input, output, session):
    @render_maplibregl
    def maplibre():
        m = Map(zoom=3)
        m.add_layer(
            Layer(
                type=LayerType.CIRCLE,
                id=LAYER_ID,
                source=GeoJSONSource(
                    data="https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson"
                ),
                paint={"circle-color": "yellow"},
            )
        )
        return m

    @render.text
    def coords():
        return str(input.maplibre())

    @render.text
    def props():
        return str(input.maplibre_layer_earthquakes())

    @reactive.Effect
    @reactive.event(input.radius)
    async def radius():
        async with MapContext("maplibre") as m:
            m.set_paint_property(LAYER_ID, "circle-radius", input.radius())


app = App(app_ui, server)

Run this example:

poetry run uvicorn docs.examples.getting_started.reactivity:app --reload