leaflet module¶
Leaflet implementation of the map widget.
LeafletMap (MapWidget)
¶
Leaflet implementation of the map widget.
Source code in anymap/leaflet.py
class LeafletMap(MapWidget):
"""Leaflet implementation of the map widget."""
# Leaflet-specific traits
tile_layer = traitlets.Unicode("OpenStreetMap").tag(sync=True)
attribution = traitlets.Unicode("").tag(sync=True)
map_options = traitlets.Dict(default_value={}).tag(sync=True)
# Define the JavaScript module path
_esm = _esm_leaflet
_css = _css_leaflet
def __init__(
self,
center: List[float] = [51.505, -0.09],
zoom: float = 13.0,
tile_layer: str = "OpenStreetMap",
width: str = "100%",
height: str = "600px",
**kwargs,
):
"""Initialize Leaflet map widget.
Args:
center: Map center as [latitude, longitude]
zoom: Initial zoom level
tile_layer: Tile layer provider name or URL template
width: Widget width
height: Widget height
map_options: Leaflet Map Options (see https://leafletjs.com/reference.html#map-option)
**kwargs: Additional widget arguments
"""
super().__init__(
center=center,
zoom=zoom,
width=width,
height=height,
**kwargs,
)
self.tile_layer = tile_layer
def add_tile_layer(
self,
url_template: str,
attribution: str = "",
layer_id: str = None,
**options,
) -> None:
"""Add a tile layer to the map.
Args:
url_template: URL template for the tile layer
attribution: Attribution text for the layer
layer_id: Unique identifier for the layer
**options: Additional layer options
"""
if layer_id is None:
layer_id = f"tile_layer_{len(self._layers)}"
layer_config = {
"type": "tile",
"url": url_template,
"attribution": attribution,
**options,
}
self.add_layer(layer_id, layer_config)
def add_marker(
self,
latlng: List[float],
popup: str = "",
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
icon: Optional[Dict[str, Any]] = None,
draggable: bool = False,
**options,
) -> str:
"""Add a marker to the map.
Args:
latlng: Marker position as [latitude, longitude]
popup: Popup text
tooltip: Tooltip text
tooltip_options: Tooltip options
icon: Icon configuration
draggable: Whether the marker is draggable
**options: Additional marker options
Returns:
Marker ID
"""
marker_id = f"marker_{len(self._layers)}"
marker_config = {
"type": "marker",
"latlng": latlng,
"popup": popup,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
"draggable": draggable,
**options,
}
if icon:
marker_config["icon"] = icon
self.add_layer(marker_id, marker_config)
return marker_id
def add_circle(
self,
latlng: List[float],
radius: float,
color: str = "blue",
fillColor: str = "blue",
fillOpacity: float = 0.2,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a circle to the map.
Args:
latlng: Circle center as [latitude, longitude]
radius: Circle radius in meters
color: Circle stroke color
fillColor: Circle fill color
fillOpacity: Circle fill opacity
tooltip: Tooltip text
tooltip_options: Tooltip options
**options: Additional circle options
Returns:
Circle ID
"""
circle_id = f"circle_{len(self._layers)}"
circle_config = {
"type": "circle",
"latlng": latlng,
"radius": radius,
"color": color,
"fillColor": fillColor,
"fillOpacity": fillOpacity,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(circle_id, circle_config)
return circle_id
def add_polygon(
self,
latlngs: List[List[float]],
color: str = "blue",
fillColor: str = "blue",
fillOpacity: float = 0.2,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a polygon to the map.
Args:
latlngs: Polygon vertices as [[lat, lng], [lat, lng], ...]
color: Polygon stroke color
fillColor: Polygon fill color
fillOpacity: Polygon fill opacity
**options: Additional polygon options
Returns:
Polygon ID
"""
polygon_id = f"polygon_{len(self._layers)}"
polygon_config = {
"type": "polygon",
"latlngs": latlngs,
"color": color,
"fillColor": fillColor,
"fillOpacity": fillOpacity,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(polygon_id, polygon_config)
return polygon_id
def add_polyline(
self,
latlngs: List[List[float]],
color: str = "blue",
weight: float = 3,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a polyline to the map.
Args:
latlngs: Polyline vertices as [[lat, lng], [lat, lng], ...]
color: Polyline color
weight: Polyline weight
**options: Additional polyline options
Returns:
Polyline ID
"""
polyline_id = f"polyline_{len(self._layers)}"
polyline_config = {
"type": "polyline",
"latlngs": latlngs,
"color": color,
"weight": weight,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(polyline_id, polyline_config)
return polyline_id
def add_geojson(
self,
data: Union[str, Dict[str, Any]],
style: Optional[Dict[str, Any]] = None,
**options,
) -> str:
"""Add GeoJSON data to the map.
Args:
data: GeoJSON data as string or dict
style: Style configuration
**options: Additional GeoJSON options
Returns:
GeoJSON layer ID
"""
geojson_id = f"geojson_{len(self._layers)}"
geojson_config = {
"type": "geojson",
"data": data,
**options,
}
if style:
geojson_config["style"] = style
self.add_layer(geojson_id, geojson_config)
return geojson_id
def fit_bounds(self, bounds: List[List[float]]) -> None:
"""Fit the map view to given bounds.
Args:
bounds: Bounds as [[south, west], [north, east]]
"""
self.call_js_method("fitBounds", bounds)
def _generate_html_template(
self, map_state: Dict[str, Any], title: str, **kwargs
) -> str:
"""Generate the HTML template with map state for Leaflet."""
# Get tile layer URL template
tile_providers = {
"OpenStreetMap": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
"CartoDB.Positron": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png",
"CartoDB.DarkMatter": "https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png",
"Stamen.Terrain": "https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.jpg",
"Stamen.Watercolor": "https://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg",
}
tile_url = tile_providers.get(map_state.get("tile_layer", "OpenStreetMap"))
if not tile_url:
tile_url = map_state.get("tile_layer", tile_providers["OpenStreetMap"])
html_template = f"""
<!DOCTYPE html>
<html>
<head>
<title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<style>
body {{
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}}
#map {{
width: {map_state.get('width', '100%')};
height: {map_state.get('height', '600px')};
}}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<script>
// Initialize the map
var map = L.map('map', {{
center: {map_state.get('center', [51.505, -0.09])},
zoom: {map_state.get('zoom', 13)}
}});
// Add tile layer
L.tileLayer('{tile_url}', {{
attribution: '© OpenStreetMap contributors'
}}).addTo(map);
// Add layers
var layers = {json.dumps(map_state.get('_layers', {}))};
for (var layerId in layers) {{
var layer = layers[layerId];
var leafletLayer = null;
if (layer.type === 'tile') {{
leafletLayer = L.tileLayer(layer.url, {{
attribution: layer.attribution || ''
}});
}} else if (layer.type === 'marker') {{
leafletLayer = L.marker(layer.latlng, {{
draggable: layer.draggable || false
}});
if (layer.popup) {{
leafletLayer.bindPopup(layer.popup);
}}
if (layer.tooltip) {{
leafletLayer.bindTooltip(layer.tooltip);
}}
}} else if (layer.type === 'circle') {{
leafletLayer = L.circle(layer.latlng, {{
radius: layer.radius,
color: layer.color || 'blue',
fillColor: layer.fillColor || 'blue',
fillOpacity: layer.fillOpacity || 0.2
}});
}} else if (layer.type === 'polygon') {{
leafletLayer = L.polygon(layer.latlngs, {{
color: layer.color || 'blue',
fillColor: layer.fillColor || 'blue',
fillOpacity: layer.fillOpacity || 0.2
}});
}} else if (layer.type === 'polyline') {{
leafletLayer = L.polyline(layer.latlngs, {{
color: layer.color || 'blue',
weight: layer.weight || 3
}});
}} else if (layer.type === 'geojson') {{
leafletLayer = L.geoJSON(layer.data, layer.style || {{}});
}}
if (leafletLayer) {{
leafletLayer.addTo(map);
}}
}}
</script>
</body>
</html>
"""
return html_template
__init__(self, center=[51.505, -0.09], zoom=13.0, tile_layer='OpenStreetMap', width='100%', height='600px', **kwargs)
special
¶
Initialize Leaflet map widget.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
center |
List[float] |
Map center as [latitude, longitude] |
[51.505, -0.09] |
zoom |
float |
Initial zoom level |
13.0 |
tile_layer |
str |
Tile layer provider name or URL template |
'OpenStreetMap' |
width |
str |
Widget width |
'100%' |
height |
str |
Widget height |
'600px' |
map_options |
Leaflet Map Options (see https://leafletjs.com/reference.html#map-option) |
required | |
**kwargs |
Additional widget arguments |
{} |
Source code in anymap/leaflet.py
def __init__(
self,
center: List[float] = [51.505, -0.09],
zoom: float = 13.0,
tile_layer: str = "OpenStreetMap",
width: str = "100%",
height: str = "600px",
**kwargs,
):
"""Initialize Leaflet map widget.
Args:
center: Map center as [latitude, longitude]
zoom: Initial zoom level
tile_layer: Tile layer provider name or URL template
width: Widget width
height: Widget height
map_options: Leaflet Map Options (see https://leafletjs.com/reference.html#map-option)
**kwargs: Additional widget arguments
"""
super().__init__(
center=center,
zoom=zoom,
width=width,
height=height,
**kwargs,
)
self.tile_layer = tile_layer
add_circle(self, latlng, radius, color='blue', fillColor='blue', fillOpacity=0.2, tooltip='', tooltip_options=None, **options)
¶
Add a circle to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
latlng |
List[float] |
Circle center as [latitude, longitude] |
required |
radius |
float |
Circle radius in meters |
required |
color |
str |
Circle stroke color |
'blue' |
fillColor |
str |
Circle fill color |
'blue' |
fillOpacity |
float |
Circle fill opacity |
0.2 |
tooltip |
str |
Tooltip text |
'' |
tooltip_options |
Optional[Dict] |
Tooltip options |
None |
**options |
Additional circle options |
{} |
Returns:
Type | Description |
---|---|
str |
Circle ID |
Source code in anymap/leaflet.py
def add_circle(
self,
latlng: List[float],
radius: float,
color: str = "blue",
fillColor: str = "blue",
fillOpacity: float = 0.2,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a circle to the map.
Args:
latlng: Circle center as [latitude, longitude]
radius: Circle radius in meters
color: Circle stroke color
fillColor: Circle fill color
fillOpacity: Circle fill opacity
tooltip: Tooltip text
tooltip_options: Tooltip options
**options: Additional circle options
Returns:
Circle ID
"""
circle_id = f"circle_{len(self._layers)}"
circle_config = {
"type": "circle",
"latlng": latlng,
"radius": radius,
"color": color,
"fillColor": fillColor,
"fillOpacity": fillOpacity,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(circle_id, circle_config)
return circle_id
add_geojson(self, data, style=None, **options)
¶
Add GeoJSON data to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data |
Union[str, Dict[str, Any]] |
GeoJSON data as string or dict |
required |
style |
Optional[Dict[str, Any]] |
Style configuration |
None |
**options |
Additional GeoJSON options |
{} |
Returns:
Type | Description |
---|---|
str |
GeoJSON layer ID |
Source code in anymap/leaflet.py
def add_geojson(
self,
data: Union[str, Dict[str, Any]],
style: Optional[Dict[str, Any]] = None,
**options,
) -> str:
"""Add GeoJSON data to the map.
Args:
data: GeoJSON data as string or dict
style: Style configuration
**options: Additional GeoJSON options
Returns:
GeoJSON layer ID
"""
geojson_id = f"geojson_{len(self._layers)}"
geojson_config = {
"type": "geojson",
"data": data,
**options,
}
if style:
geojson_config["style"] = style
self.add_layer(geojson_id, geojson_config)
return geojson_id
add_marker(self, latlng, popup='', tooltip='', tooltip_options=None, icon=None, draggable=False, **options)
¶
Add a marker to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
latlng |
List[float] |
Marker position as [latitude, longitude] |
required |
popup |
str |
Popup text |
'' |
tooltip |
str |
Tooltip text |
'' |
tooltip_options |
Optional[Dict] |
Tooltip options |
None |
icon |
Optional[Dict[str, Any]] |
Icon configuration |
None |
draggable |
bool |
Whether the marker is draggable |
False |
**options |
Additional marker options |
{} |
Returns:
Type | Description |
---|---|
str |
Marker ID |
Source code in anymap/leaflet.py
def add_marker(
self,
latlng: List[float],
popup: str = "",
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
icon: Optional[Dict[str, Any]] = None,
draggable: bool = False,
**options,
) -> str:
"""Add a marker to the map.
Args:
latlng: Marker position as [latitude, longitude]
popup: Popup text
tooltip: Tooltip text
tooltip_options: Tooltip options
icon: Icon configuration
draggable: Whether the marker is draggable
**options: Additional marker options
Returns:
Marker ID
"""
marker_id = f"marker_{len(self._layers)}"
marker_config = {
"type": "marker",
"latlng": latlng,
"popup": popup,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
"draggable": draggable,
**options,
}
if icon:
marker_config["icon"] = icon
self.add_layer(marker_id, marker_config)
return marker_id
add_polygon(self, latlngs, color='blue', fillColor='blue', fillOpacity=0.2, tooltip='', tooltip_options=None, **options)
¶
Add a polygon to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
latlngs |
List[List[float]] |
Polygon vertices as [[lat, lng], [lat, lng], ...] |
required |
color |
str |
Polygon stroke color |
'blue' |
fillColor |
str |
Polygon fill color |
'blue' |
fillOpacity |
float |
Polygon fill opacity |
0.2 |
**options |
Additional polygon options |
{} |
Returns:
Type | Description |
---|---|
str |
Polygon ID |
Source code in anymap/leaflet.py
def add_polygon(
self,
latlngs: List[List[float]],
color: str = "blue",
fillColor: str = "blue",
fillOpacity: float = 0.2,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a polygon to the map.
Args:
latlngs: Polygon vertices as [[lat, lng], [lat, lng], ...]
color: Polygon stroke color
fillColor: Polygon fill color
fillOpacity: Polygon fill opacity
**options: Additional polygon options
Returns:
Polygon ID
"""
polygon_id = f"polygon_{len(self._layers)}"
polygon_config = {
"type": "polygon",
"latlngs": latlngs,
"color": color,
"fillColor": fillColor,
"fillOpacity": fillOpacity,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(polygon_id, polygon_config)
return polygon_id
add_polyline(self, latlngs, color='blue', weight=3, tooltip='', tooltip_options=None, **options)
¶
Add a polyline to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
latlngs |
List[List[float]] |
Polyline vertices as [[lat, lng], [lat, lng], ...] |
required |
color |
str |
Polyline color |
'blue' |
weight |
float |
Polyline weight |
3 |
**options |
Additional polyline options |
{} |
Returns:
Type | Description |
---|---|
str |
Polyline ID |
Source code in anymap/leaflet.py
def add_polyline(
self,
latlngs: List[List[float]],
color: str = "blue",
weight: float = 3,
tooltip: str = "",
tooltip_options: Optional[Dict] = None,
**options,
) -> str:
"""Add a polyline to the map.
Args:
latlngs: Polyline vertices as [[lat, lng], [lat, lng], ...]
color: Polyline color
weight: Polyline weight
**options: Additional polyline options
Returns:
Polyline ID
"""
polyline_id = f"polyline_{len(self._layers)}"
polyline_config = {
"type": "polyline",
"latlngs": latlngs,
"color": color,
"weight": weight,
"tooltip": tooltip,
"tooltip_options": tooltip_options,
**options,
}
self.add_layer(polyline_id, polyline_config)
return polyline_id
add_tile_layer(self, url_template, attribution='', layer_id=None, **options)
¶
Add a tile layer to the map.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url_template |
str |
URL template for the tile layer |
required |
attribution |
str |
Attribution text for the layer |
'' |
layer_id |
str |
Unique identifier for the layer |
None |
**options |
Additional layer options |
{} |
Source code in anymap/leaflet.py
def add_tile_layer(
self,
url_template: str,
attribution: str = "",
layer_id: str = None,
**options,
) -> None:
"""Add a tile layer to the map.
Args:
url_template: URL template for the tile layer
attribution: Attribution text for the layer
layer_id: Unique identifier for the layer
**options: Additional layer options
"""
if layer_id is None:
layer_id = f"tile_layer_{len(self._layers)}"
layer_config = {
"type": "tile",
"url": url_template,
"attribution": attribution,
**options,
}
self.add_layer(layer_id, layer_config)
fit_bounds(self, bounds)
¶
Fit the map view to given bounds.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
bounds |
List[List[float]] |
Bounds as [[south, west], [north, east]] |
required |
Source code in anymap/leaflet.py
def fit_bounds(self, bounds: List[List[float]]) -> None:
"""Fit the map view to given bounds.
Args:
bounds: Bounds as [[south, west], [north, east]]
"""
self.call_js_method("fitBounds", bounds)