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:
input.{output_id}_clicked
: Sends coordinates of the clicked location on the map.input.{output_id}_feature_clicked
: Sends the properties of the clicked feature and its layer id.input.{output_id}_view_state
: Sends the current view state. Fired when the view state is changed.
Map updates
Use MapContext
to update your Map
object.
Example
import json
from maplibre import (
Layer,
LayerType,
Map,
MapContext,
output_maplibregl,
render_maplibregl,
)
from maplibre.controls import NavigationControl
from maplibre.sources import GeoJSONSource
from shiny import App, reactive, render, ui
LAYER_ID = "earthquakes"
CIRCLE_RADIUS = 5
app_ui = ui.page_fluid(
ui.panel_title("MapLibre for Python"),
output_maplibregl("mapgl", height=600),
ui.div("Click on the map to print the coords.", style="padding: 10px;"),
ui.output_text_verbatim("coords", placeholder=True),
ui.div("Click on a feature to print its props.", style="padding: 10px;"),
ui.output_text_verbatim("props", placeholder=True),
ui.div("Move map or zoom to update view state.", style="padding: 10px;"),
ui.output_text_verbatim("view_state", placeholder=True),
ui.input_slider("radius", "Radius", value=CIRCLE_RADIUS, min=1, max=10),
)
circle_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"},
)
def server(input, output, session):
@render_maplibregl
def mapgl():
m = Map(zoom=3, pitch=40)
m.add_control(NavigationControl())
m.add_layer(circle_layer)
return m
@render.text
def coords():
return str(input.mapgl_clicked())
@render.text
def view_state():
return json.dumps(input.mapgl_view_state(), indent=2)
@render.text
def props():
return str(input.mapgl_feature_clicked())
@reactive.Effect
@reactive.event(input.radius)
async def radius():
async with MapContext("mapgl") as m:
m.set_paint_property(LAYER_ID, "circle-radius", input.radius())
app = App(app_ui, server)
Run this example: