Creative MapLibreum Examples & Tutorials¶
MapLibreum ships with a curated set of base styles (such as basic
, streets
, and satellite
) so you can start with a clean and familiar look straight away.
1. Quick Start: Hello MapLibreum¶
Display a map centered on New York City and add a friendly greeting marker.
from maplibreum import Map
m = Map(center=[40.7128, -74.0060], zoom=12)
m.add_marker(popup="Welcome to NYC!")
m
add_marker
lets you customize coordinates, popup text, marker color, clustering, icons, tooltips, and draggability.
2. Custom Icons & Tooltips¶
Use a BeautifyIcon for eye-catching markers that provide extra context to your users.
from maplibreum import Map
from maplibreum.markers import BeautifyIcon
m = Map(center=[48.8566, 2.3522], zoom=13)
icon = BeautifyIcon(icon="fa fa-coffee", background_color="#d35400")
m.add_marker(coordinates=[48.8566, 2.3522],
icon=icon,
tooltip="Coffee shop")
m
BeautifyIcon
accepts icon classes, colors, and shapes, making markers visually rich.
3. Visualizing Density with Heatmaps¶
MapLibreum can turn real event datasets into density surfaces. The example below plots a dozen magnitude 2.5–3.3 earthquakes recorded around the San Andreas Fault in spring 2024, weighting the heatmap by the reported magnitude.
from maplibreum import Map
earthquake_points = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.201, 36.80667]},
"properties": {"mag": 2.74, "place": "11 km E of Tres Pinos, CA", "time": 1719534039910},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.29283, 35.91517]},
"properties": {"mag": 3.1, "place": "27 km SE of Lopez Point, CA", "time": 1719462724510},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.7845, 38.81333]},
"properties": {"mag": 2.59, "place": "5 km NNW of The Geysers, CA", "time": 1719456625400},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-120.64, 36.075]},
"properties": {"mag": 3.24, "place": "25 km E of San Ardo, CA", "time": 1719350411620},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.80017, 38.827]},
"properties": {"mag": 3.3, "place": "7 km WNW of Cobb, CA", "time": 1719231743120},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.28283, 36.65633]},
"properties": {"mag": 2.87, "place": "15 km S of Tres Pinos, CA", "time": 1718722685950},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-119.99567, 37.40267]},
"properties": {"mag": 2.83, "place": "10 km SSW of Mariposa, CA", "time": 1718664848280},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.29733, 36.8535]},
"properties": {"mag": 2.59, "place": "7 km NNE of Tres Pinos, CA", "time": 1718623933030},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.256, 36.634]},
"properties": {"mag": 2.73, "place": "15 km NNW of Pinnacles, CA", "time": 1718587308000},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.63533, 37.25767]},
"properties": {"mag": 3.01, "place": "14 km NNE of Morgan Hill, CA", "time": 1718519361180},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.81, 37.4845]},
"properties": {"mag": 2.92, "place": "11 km ENE of Milpitas, CA", "time": 1718342726340},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-121.05933, 36.54883]},
"properties": {"mag": 2.68, "place": "8 km E of Pinnacles, CA", "time": 1718322168990},
},
],
}
source = {"type": "geojson", "data": earthquake_points}
m = Map(center=[-121.5, 37.1], zoom=6)
m.add_heatmap_layer(
"bay-area-quakes",
source,
paint={
"heatmap-weight": [
"interpolate",
["linear"],
["get", "mag"],
2.5,
0.2,
3.5,
1.0,
],
"heatmap-radius": [
"interpolate",
["linear"],
["zoom"],
5,
20,
10,
45,
],
"heatmap-intensity": 1.1,
},
)
m
Heatmap weighting comes from the mag
property so stronger shaking brightens the visualization. Tweak the paint
settings to experiment with radii, intensity, and gradient stops.
4. Choropleth Map¶
Shade regions based on attribute values such as population or median income.
from maplibreum import Map, Choropleth
# Example GeoJSON with polygon features (simplified for demo)
geojson_polygons = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"id": "area1", "name": "Downtown"},
"geometry": {
"type": "Polygon",
"coordinates": [[[-74.01, 40.71], [-74.00, 40.71], [-74.00, 40.72], [-74.01, 40.72], [-74.01, 40.71]]]
}
},
{
"type": "Feature",
"properties": {"id": "area2", "name": "Midtown"},
"geometry": {
"type": "Polygon",
"coordinates": [[[-74.01, 40.72], [-74.00, 40.72], [-74.00, 40.73], [-74.01, 40.73], [-74.01, 40.72]]]
}
}
]
}
# Population data mapping feature IDs to counts
pop_data = {"area1": 25000, "area2": 45000}
m = Map(center=[-74.005, 40.72], zoom=13)
Choropleth(geojson_polygons, pop_data, legend_title="Population").add_to(m)
m
The Choropleth
class computes data bins, colors each feature, and adds a legend automatically.
5. Marker Clustering¶
Group many markers together for a cleaner view. Here we cluster notable New York City art museums so the display stays readable as you zoom in.
from maplibreum import Map
nyc_museums = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9632, 40.7794]},
"properties": {"name": "The Metropolitan Museum of Art"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9776, 40.7614]},
"properties": {"name": "The Museum of Modern Art"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.959, 40.783]},
"properties": {"name": "Solomon R. Guggenheim Museum"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-74.0089, 40.7396]},
"properties": {"name": "Whitney Museum of American Art"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9735, 40.7813]},
"properties": {"name": "American Museum of Natural History"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9636, 40.6712]},
"properties": {"name": "Brooklyn Museum"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9927, 40.7223]},
"properties": {"name": "New Museum"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.8468, 40.7455]},
"properties": {"name": "Queens Museum"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9235, 40.7563]},
"properties": {"name": "Museum of the Moving Image"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9996, 40.7645]},
"properties": {"name": "Intrepid Sea, Air & Space Museum"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9173, 40.8317]},
"properties": {"name": "The Bronx Museum of the Arts"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9675, 40.7712]},
"properties": {"name": "The Frick Collection"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9519, 40.7925]},
"properties": {"name": "Museum of the City of New York"},
},
],
}
m = Map(center=[-73.985, 40.758], zoom=11)
m.add_clustered_geojson(nyc_museums, name="nyc-museums", radius=60, max_zoom=15)
m
add_clustered_geojson
builds a single clustered source with count and point layers, producing the same arrangement every run because the dataset is deterministic. Zoom in to break apart clusters and inspect individual museum locations.
6. Time-Lapse Playback¶
Animate timestamped features—ideal for tracking movement or events over time. This example replays a westbound Thames Clippers commuter run from Greenwich to Battersea recorded on 9 April 2024.
from maplibreum import Map
from maplibreum.timedimension import TimeDimension
thames_commute = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.0076, 51.4827]},
"properties": {"time": "2024-04-09T07:00:00Z", "stop": "Greenwich Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.0232, 51.5056]},
"properties": {"time": "2024-04-09T07:08:00Z", "stop": "Canary Wharf Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.0769, 51.5081]},
"properties": {"time": "2024-04-09T07:16:00Z", "stop": "Tower Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.1031, 51.5118]},
"properties": {"time": "2024-04-09T07:22:00Z", "stop": "Blackfriars Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.1223, 51.5074]},
"properties": {"time": "2024-04-09T07:27:00Z", "stop": "Embankment Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.1247, 51.5009]},
"properties": {"time": "2024-04-09T07:30:00Z", "stop": "Westminster Pier"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-0.144, 51.4813]},
"properties": {"time": "2024-04-09T07:37:00Z", "stop": "Battersea Power Station Pier"},
},
],
}
m = Map(center=[-0.09, 51.505], zoom=11)
TimeDimension(thames_commute, options={"interval": 1200}).add_to(m)
m
TimeDimension
stores the GeoJSON and playback configuration so the template can iterate through the time
stamps. The 1.2-second interval keeps the animation brisk while still letting you see each pier stop.