AnyMap Mapbox GL JS Examples¶
This notebook demonstrates the Mapbox GL JS backend for anymap, showcasing advanced mapping features including 3D terrain, 3D buildings, custom controls, and atmospheric fog effects.
# Import required modules
from anymap import MapboxMap
import json
import os
# Note: You need a Mapbox access token to use the Mapbox backend
# Get a free token at https://account.mapbox.com/access-tokens/
# Set it as an environment variable: export MAPBOX_TOKEN="your_token_here"
# Or pass it directly when creating the map: MapboxMap(access_token="your_token")
print("AnyMap with Mapbox backend loaded successfully!")
AnyMap with Mapbox backend loaded successfully!
Basic Mapbox Map¶
Let's start with a basic Mapbox map. The access token is automatically handled.
# Create a basic Mapbox map
# NOTE: Replace "your_token_here" with your actual Mapbox access token
# or set the MAPBOX_TOKEN environment variable
m = MapboxMap(
center=[37.7749, -122.4194], # San Francisco
zoom=12,
height="600px",
style="mapbox://styles/mapbox/streets-v12",
# access_token="your_token_here" # Replace with your actual token
)
print(f"Access token set: {bool(m.access_token)}")
print(f"Map style: {m.style}")
m
Access token set: False Map style: mapbox://styles/mapbox/streets-v12
/home/runner/work/anymap/anymap/anymap/mapbox.py:111: UserWarning: No Mapbox access token found. Please set MAPBOX_ACCESS_TOKEN environment variable or pass access_token parameter. Get a free token at https://account.mapbox.com/access-tokens/ warnings.warn(
m = MapboxMap(
center=[37.7749, -122.4194], # San Francisco
zoom=12,
height="600px",
style="mapbox://styles/mapbox/streets-v12",
# access_token="your_token_here" # Replace with your actual token
)
m.add_basemap("Esri.WorldImagery")
m
Mapbox Styles¶
Mapbox offers various built-in styles. Let's try the satellite style.
# Change to satellite style
m.set_style("mapbox://styles/mapbox/satellite-v9")
m
3D Terrain and Buildings¶
One of Mapbox's powerful features is 3D terrain and building visualization.
# Create a new map focused on a mountainous area
m3d = MapboxMap(
center=[46.8182, 8.2275], # Swiss Alps
zoom=12,
pitch=60,
bearing=45,
height="600px",
style="mapbox://styles/mapbox/satellite-v9",
)
# Add 3D terrain
terrain_config = {"source": "mapbox-dem", "exaggeration": 1.5}
m3d.set_terrain(terrain_config)
# Add atmospheric fog for realism
fog_config = {
"color": "rgb(186, 210, 235)",
"high-color": "rgb(36, 92, 223)",
"horizon-blend": 0.02,
"space-color": "rgb(11, 11, 25)",
"star-intensity": 0.6,
}
m3d.set_fog(fog_config)
print("3D terrain and fog added to the map")
m3d
3D terrain and fog added to the map
Adding Controls¶
Mapbox provides various interactive controls.
# Add various controls to the map
m3d.add_control("navigation", "top-left")
m3d.add_control("scale", "bottom-left")
m3d.add_control("fullscreen", "top-right")
print("Navigation, scale, and fullscreen controls added")
Navigation, scale, and fullscreen controls added
Urban 3D Buildings¶
Let's create a map showcasing 3D buildings in a urban environment.
# Create a map focused on New York City
nyc_map = MapboxMap(
center=[40.7589, -73.9851], # Times Square
zoom=16,
pitch=60,
bearing=30,
height="600px",
style="mapbox://styles/mapbox/streets-v12",
)
# Add 3D buildings
nyc_map.add_3d_buildings()
# Add navigation control
nyc_map.add_control("navigation", "top-left")
print("3D buildings added to NYC map")
nyc_map
3D buildings added to NYC map
Adding Data Layers¶
Let's add some GeoJSON data to visualize points of interest.
# Sample data for NYC landmarks
nyc_landmarks = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-74.0445, 40.6892]},
"properties": {"name": "Statue of Liberty", "type": "monument"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-74.0060, 40.7128]},
"properties": {"name": "One World Trade Center", "type": "building"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9857, 40.7484]},
"properties": {"name": "Central Park", "type": "park"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.9442, 40.8176]},
"properties": {"name": "Yankee Stadium", "type": "stadium"},
},
],
}
# Add the landmarks as a circle layer
nyc_map.add_geojson_layer(
layer_id="landmarks",
geojson_data=nyc_landmarks,
layer_type="circle",
paint={
"circle-radius": 8,
"circle-color": "#FF6B6B",
"circle-stroke-width": 2,
"circle-stroke-color": "#FFFFFF",
"circle-opacity": 0.8,
},
)
# Add markers with popups
nyc_map.add_marker(
40.6892,
-74.0445,
"<h3>Statue of Liberty</h3><p>Symbol of freedom and democracy</p>",
)
nyc_map.add_marker(
40.7484, -73.9857, "<h3>Central Park</h3><p>Manhattan's green oasis</p>"
)
print("NYC landmarks added to the map")
print(f"Current layers: {list(nyc_map.get_layers().keys())}")
Statue of Liberty
Symbol of freedom and democracy
", ) nyc_map.add_marker( 40.7484, -73.9857, "Central Park
Manhattan's green oasis
" ) print("NYC landmarks added to the map") print(f"Current layers: {list(nyc_map.get_layers().keys())}")NYC landmarks added to the map Current layers: ['3d-buildings', 'landmarks']
Multi-Cell Rendering Test¶
Test that the same map instance renders correctly in multiple cells.
# Display the NYC map again - should show all layers
print("Displaying NYC map again with all layers:")
print(f"Layers: {list(nyc_map.get_layers().keys())}")
print(f"Sources: {list(nyc_map.get_sources().keys())}")
nyc_map
Displaying NYC map again with all layers: Layers: ['3d-buildings', 'landmarks'] Sources: ['landmarks_source']
Event Handling¶
Set up event handlers to capture user interactions.
# Store events for demonstration
map_events = []
def on_map_click(event):
lat, lng = event["lngLat"]
map_events.append(f"Clicked at: {lat:.4f}, {lng:.4f}")
print(f"Map clicked at: {lat:.4f}, {lng:.4f}")
def on_map_move(event):
center = event.get("center", [0, 0])
zoom = event.get("zoom", 0)
print(f"Map moved to: {center[0]:.4f}, {center[1]:.4f} at zoom {zoom:.2f}")
# Register event handlers
nyc_map.on_map_event("click", on_map_click)
nyc_map.on_map_event("moveend", on_map_move)
print("Event handlers registered. Try clicking and moving the map!")
Event handlers registered. Try clicking and moving the map!
Comparison with MapLibre¶
Let's create a side-by-side comparison with MapLibre to show both backends work independently.
from anymap import MapLibreMap
# Create a MapLibre map for comparison
maplibre_map = MapLibreMap(
center=[37.7749, -122.4194], # San Francisco
zoom=12,
height="400px",
style="https://demotiles.maplibre.org/style.json",
)
# Add some data to differentiate
sf_data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.4194, 37.7749]},
"properties": {"name": "San Francisco City Hall"},
}
],
}
maplibre_map.add_geojson_layer(
"sf_poi", sf_data, "circle", {"circle-color": "#50C878", "circle-radius": 10}
)
print("MapLibre map (San Francisco):")
maplibre_map
MapLibre map (San Francisco):
# Create a Mapbox map of the same location for comparison
mapbox_sf = MapboxMap(
center=[37.7749, -122.4194], # San Francisco
zoom=12,
height="400px",
style="mapbox://styles/mapbox/streets-v12",
)
mapbox_sf.add_geojson_layer(
"sf_poi_mapbox", sf_data, "circle", {"circle-color": "#FF6B6B", "circle-radius": 10}
)
print("Mapbox map (San Francisco):")
mapbox_sf
Mapbox map (San Francisco):
Advanced Mapbox Features¶
Let's showcase some advanced Mapbox-specific features like custom terrain sources.
# Create a map of the Grand Canyon with enhanced terrain
canyon_map = MapboxMap(
center=[36.1069, -112.1129], # Grand Canyon
zoom=13,
pitch=70,
bearing=150,
height="600px",
style="mapbox://styles/mapbox/satellite-v9",
)
# Add terrain with higher exaggeration for dramatic effect
canyon_terrain = {"source": "mapbox-dem", "exaggeration": 2.0}
canyon_map.set_terrain(canyon_terrain)
# Add enhanced atmospheric fog
canyon_fog = {
"color": "rgb(255, 255, 255)",
"high-color": "rgb(200, 200, 255)",
"horizon-blend": 0.1,
"space-color": "rgb(11, 11, 25)",
"star-intensity": 0.0,
}
canyon_map.set_fog(canyon_fog)
# Add controls
canyon_map.add_control("navigation", "top-left")
canyon_map.add_control("scale", "bottom-left")
print("Grand Canyon with enhanced 3D terrain")
canyon_map
Grand Canyon with enhanced 3D terrain
Layer Management¶
Demonstrate layer management capabilities.
# Create a simple map for layer management demo
layer_demo = MapboxMap(center=[40.7128, -74.0060], zoom=10, height="400px") # NYC
# Add multiple layers
demo_data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-74.0060, 40.7128]},
"properties": {"name": "Point 1"},
}
],
}
layer_demo.add_geojson_layer("layer1", demo_data, "circle", {"circle-color": "red"})
layer_demo.add_geojson_layer("layer2", demo_data, "circle", {"circle-color": "blue"})
layer_demo.add_geojson_layer("layer3", demo_data, "circle", {"circle-color": "green"})
print(f"Layers before cleanup: {list(layer_demo.get_layers().keys())}")
layer_demo
Layers before cleanup: ['layer1', 'layer2', 'layer3']
# Clear some layers
layer_demo.remove_layer("layer2")
print(f"After removing layer2: {list(layer_demo.get_layers().keys())}")
# Clear all layers
layer_demo.clear_layers()
print(f"After clearing all layers: {list(layer_demo.get_layers().keys())}")
print(f"Sources still exist: {list(layer_demo.get_sources().keys())}")
# Display the map without layers
layer_demo
After removing layer2: ['layer1', 'layer3'] After clearing all layers: [] Sources still exist: ['layer1_source', 'layer2_source', 'layer3_source']
Summary¶
This notebook demonstrated the key features of AnyMap's Mapbox GL JS backend:
✅ Mapbox Integration: Full integration with Mapbox GL JS v3.13.0
✅ Access Token Management: Automatic token handling with fallbacks
✅ 3D Terrain & Buildings: Support for 3D terrain exaggeration and building visualization
✅ Atmospheric Effects: Fog and lighting effects for realistic mapping
✅ Interactive Controls: Navigation, scale, fullscreen, and geolocation controls
✅ Multi-cell Rendering: Persistent layer state across Jupyter cells
✅ Event Handling: Click and move event capture
✅ Layer Management: Full CRUD operations for map layers and sources
✅ Style Flexibility: Support for built-in Mapbox styles and custom styles
✅ Independence: Works alongside MapLibre backend without conflicts
The Mapbox backend provides access to Mapbox's premium features while maintaining the same simple API as the MapLibre backend.