Skip to content

openlayers module

OpenLayers map widget implementation.

OpenLayersMap (MapWidget)

Interactive map widget using OpenLayers.

This class provides a Python interface to OpenLayers maps with full bidirectional communication through anywidget. OpenLayers excels at WMS/WMTS support and projection handling.

Examples:

>>> from anymap_ts import OpenLayersMap
>>> m = OpenLayersMap(center=[-122.4, 37.8], zoom=10)
>>> m.add_basemap("OpenStreetMap")
>>> m.add_wms_layer(
...     url="https://example.com/wms",
...     layers="layer_name",
...     name="WMS Layer"
... )
>>> m
Source code in anymap_ts/openlayers.py
class OpenLayersMap(MapWidget):
    """Interactive map widget using OpenLayers.

    This class provides a Python interface to OpenLayers maps with
    full bidirectional communication through anywidget. OpenLayers
    excels at WMS/WMTS support and projection handling.

    Example:
        >>> from anymap_ts import OpenLayersMap
        >>> m = OpenLayersMap(center=[-122.4, 37.8], zoom=10)
        >>> m.add_basemap("OpenStreetMap")
        >>> m.add_wms_layer(
        ...     url="https://example.com/wms",
        ...     layers="layer_name",
        ...     name="WMS Layer"
        ... )
        >>> m
    """

    # ESM module for frontend
    _esm = STATIC_DIR / "openlayers.js"

    # OpenLayers-specific traits
    projection = traitlets.Unicode("EPSG:3857").tag(sync=True)
    rotation = traitlets.Float(0.0).tag(sync=True)

    # Layer tracking
    _layer_dict = traitlets.Dict({}).tag(sync=True)

    def __init__(
        self,
        center: Tuple[float, float] = (0.0, 0.0),
        zoom: float = 2.0,
        width: str = "100%",
        height: str = "600px",
        projection: str = "EPSG:3857",
        rotation: float = 0.0,
        controls: Optional[Dict[str, Any]] = None,
        **kwargs,
    ):
        """Initialize an OpenLayers map.

        Args:
            center: Map center as (longitude, latitude).
            zoom: Initial zoom level.
            width: Map width as CSS string.
            height: Map height as CSS string.
            projection: Map projection (default EPSG:3857).
            rotation: Map rotation in radians.
            controls: Dict of controls to add.
            **kwargs: Additional widget arguments.
        """
        super().__init__(
            center=list(center),
            zoom=zoom,
            width=width,
            height=height,
            projection=projection,
            rotation=rotation,
            **kwargs,
        )

        # Initialize layer dictionary
        self._layer_dict = {"Background": []}

        # Add default controls
        if controls is None:
            controls = {"zoom": True, "attribution": True}

        for control_name, config in controls.items():
            if config:
                self.add_control(
                    control_name, **(config if isinstance(config, dict) else {})
                )

    # -------------------------------------------------------------------------
    # Basemap Methods
    # -------------------------------------------------------------------------

    def add_basemap(
        self,
        basemap: str = "OpenStreetMap",
        attribution: Optional[str] = None,
        **kwargs,
    ) -> None:
        """Add a basemap layer.

        Args:
            basemap: Name of basemap provider (e.g., "OpenStreetMap", "CartoDB.Positron").
            attribution: Custom attribution text.
            **kwargs: Additional options.
        """
        url, default_attribution = get_basemap_url(basemap)
        self.call_js_method(
            "addBasemap",
            url,
            attribution=attribution or default_attribution,
            name=basemap,
            **kwargs,
        )

        basemaps = self._layer_dict.get("Basemaps", [])
        if basemap not in basemaps:
            self._layer_dict = {
                **self._layer_dict,
                "Basemaps": basemaps + [basemap],
            }

    # -------------------------------------------------------------------------
    # Tile Layer Methods
    # -------------------------------------------------------------------------

    def add_tile_layer(
        self,
        url: str,
        name: Optional[str] = None,
        attribution: str = "",
        min_zoom: int = 0,
        max_zoom: int = 22,
        opacity: float = 1.0,
        **kwargs,
    ) -> None:
        """Add an XYZ tile layer.

        Args:
            url: Tile URL template with {x}, {y}, {z} placeholders.
            name: Layer name.
            attribution: Attribution text.
            min_zoom: Minimum zoom level.
            max_zoom: Maximum zoom level.
            opacity: Layer opacity.
            **kwargs: Additional options.
        """
        layer_id = name or f"tiles-{len(self._layers)}"

        self.call_js_method(
            "addTileLayer",
            url,
            name=layer_id,
            attribution=attribution,
            minZoom=min_zoom,
            maxZoom=max_zoom,
            opacity=opacity,
            **kwargs,
        )

        self._layers = {
            **self._layers,
            layer_id: {"id": layer_id, "type": "tile"},
        }

    # -------------------------------------------------------------------------
    # Vector Data Methods
    # -------------------------------------------------------------------------

    def add_vector(
        self,
        data: Any,
        name: Optional[str] = None,
        style: Optional[Dict] = None,
        fit_bounds: bool = True,
        **kwargs,
    ) -> None:
        """Add vector data to the map.

        Args:
            data: GeoJSON dict, GeoDataFrame, or path to vector file.
            name: Layer name.
            style: Style configuration dict.
            fit_bounds: Whether to fit map to data bounds.
            **kwargs: Additional layer options.
        """
        geojson = to_geojson(data)
        layer_id = name or f"vector-{len(self._layers)}"

        if style is None:
            style = self._get_default_style(geojson)

        self.call_js_method(
            "addGeoJSON",
            data=geojson,
            name=layer_id,
            style=style,
            fitBounds=fit_bounds,
            **kwargs,
        )

        self._layers = {
            **self._layers,
            layer_id: {"id": layer_id, "type": "vector"},
        }

    def add_geojson(
        self,
        data: Union[str, Dict],
        name: Optional[str] = None,
        style: Optional[Dict] = None,
        fit_bounds: bool = True,
        **kwargs,
    ) -> None:
        """Add GeoJSON data to the map.

        Args:
            data: GeoJSON dict or URL to GeoJSON file.
            name: Layer name.
            style: Style configuration dict.
            fit_bounds: Whether to fit map to data bounds.
            **kwargs: Additional layer options.
        """
        self.add_vector(
            data,
            name=name,
            style=style,
            fit_bounds=fit_bounds,
            **kwargs,
        )

    def _get_default_style(self, geojson: Dict) -> Dict:
        """Get default style based on geometry type.

        Args:
            geojson: GeoJSON data.

        Returns:
            Style configuration dict.
        """
        geom_type = self._infer_geom_type(geojson)

        if geom_type in ["Point", "MultiPoint"]:
            return {
                "fillColor": "rgba(51, 136, 255, 0.8)",
                "strokeColor": "#ffffff",
                "strokeWidth": 2,
                "radius": 6,
            }
        elif geom_type in ["LineString", "MultiLineString"]:
            return {
                "strokeColor": "#3388ff",
                "strokeWidth": 3,
            }
        else:  # Polygon, MultiPolygon
            return {
                "fillColor": "rgba(51, 136, 255, 0.5)",
                "strokeColor": "#3388ff",
                "strokeWidth": 2,
            }

    def _infer_geom_type(self, geojson: Dict) -> str:
        """Infer geometry type from GeoJSON.

        Args:
            geojson: GeoJSON data.

        Returns:
            Geometry type string.
        """
        if geojson.get("type") == "FeatureCollection":
            features = geojson.get("features", [])
            if features:
                return features[0].get("geometry", {}).get("type", "Point")
        elif geojson.get("type") == "Feature":
            return geojson.get("geometry", {}).get("type", "Point")
        return "Point"

    # -------------------------------------------------------------------------
    # WMS/WMTS Methods
    # -------------------------------------------------------------------------

    def add_wms_layer(
        self,
        url: str,
        layers: str,
        name: Optional[str] = None,
        format: str = "image/png",
        transparent: bool = True,
        server_type: Optional[str] = None,
        attribution: str = "",
        **kwargs,
    ) -> None:
        """Add a WMS tile layer.

        Args:
            url: WMS service URL.
            layers: Comma-separated layer names.
            name: Layer name for the map.
            format: Image format (default: image/png).
            transparent: Whether to request transparent images.
            server_type: Server type ('mapserver', 'geoserver', 'qgis').
            attribution: Attribution text.
            **kwargs: Additional WMS parameters.
        """
        layer_id = name or f"wms-{len(self._layers)}"

        self.call_js_method(
            "addWMSLayer",
            url=url,
            layers=layers,
            name=layer_id,
            format=format,
            transparent=transparent,
            serverType=server_type,
            attribution=attribution,
            **kwargs,
        )

        self._layers = {
            **self._layers,
            layer_id: {"id": layer_id, "type": "wms"},
        }

    def add_image_wms_layer(
        self,
        url: str,
        layers: str,
        name: Optional[str] = None,
        format: str = "image/png",
        transparent: bool = True,
        server_type: Optional[str] = None,
        attribution: str = "",
        **kwargs,
    ) -> None:
        """Add a single-image WMS layer (not tiled).

        Args:
            url: WMS service URL.
            layers: Comma-separated layer names.
            name: Layer name for the map.
            format: Image format (default: image/png).
            transparent: Whether to request transparent images.
            server_type: Server type ('mapserver', 'geoserver', 'qgis').
            attribution: Attribution text.
            **kwargs: Additional WMS parameters.
        """
        layer_id = name or f"imagewms-{len(self._layers)}"

        self.call_js_method(
            "addImageWMSLayer",
            url=url,
            layers=layers,
            name=layer_id,
            format=format,
            transparent=transparent,
            serverType=server_type,
            attribution=attribution,
            **kwargs,
        )

        self._layers = {
            **self._layers,
            layer_id: {"id": layer_id, "type": "imagewms"},
        }

    # -------------------------------------------------------------------------
    # Layer Management
    # -------------------------------------------------------------------------

    def remove_layer(self, layer_id: str) -> None:
        """Remove a layer from the map.

        Args:
            layer_id: Layer identifier to remove.
        """
        if layer_id in self._layers:
            layers = dict(self._layers)
            del layers[layer_id]
            self._layers = layers
        self.call_js_method("removeLayer", layer_id)

    def set_visibility(self, layer_id: str, visible: bool) -> None:
        """Set layer visibility.

        Args:
            layer_id: Layer identifier.
            visible: Whether layer should be visible.
        """
        self.call_js_method("setVisibility", layer_id, visible)

    def set_opacity(self, layer_id: str, opacity: float) -> None:
        """Set layer opacity.

        Args:
            layer_id: Layer identifier.
            opacity: Opacity value between 0 and 1.
        """
        self.call_js_method("setOpacity", layer_id, opacity)

    # -------------------------------------------------------------------------
    # Controls
    # -------------------------------------------------------------------------

    def add_control(
        self,
        control_type: str,
        position: str = "top-right",
        **kwargs,
    ) -> None:
        """Add a map control.

        Args:
            control_type: Type of control ('zoom', 'scale', 'fullscreen', etc.).
            position: Control position.
            **kwargs: Control-specific options.
        """
        self.call_js_method("addControl", control_type, position=position, **kwargs)
        self._controls = {
            **self._controls,
            control_type: {"type": control_type, "position": position, **kwargs},
        }

    def remove_control(self, control_type: str) -> None:
        """Remove a map control.

        Args:
            control_type: Type of control to remove.
        """
        self.call_js_method("removeControl", control_type)
        if control_type in self._controls:
            controls = dict(self._controls)
            del controls[control_type]
            self._controls = controls

    # -------------------------------------------------------------------------
    # Navigation
    # -------------------------------------------------------------------------

    def set_center(self, lng: float, lat: float) -> None:
        """Set the map center.

        Args:
            lng: Longitude.
            lat: Latitude.
        """
        self.center = [lng, lat]
        self.call_js_method("setCenter", lng, lat)

    def set_zoom(self, zoom: float) -> None:
        """Set the map zoom level.

        Args:
            zoom: Zoom level.
        """
        self.zoom = zoom
        self.call_js_method("setZoom", zoom)

    def fly_to(
        self,
        lng: float,
        lat: float,
        zoom: Optional[float] = None,
        duration: int = 2000,
    ) -> None:
        """Animate to a new location.

        Args:
            lng: Target longitude.
            lat: Target latitude.
            zoom: Target zoom level (optional).
            duration: Animation duration in milliseconds.
        """
        self.call_js_method(
            "flyTo", lng, lat, zoom=zoom or self.zoom, duration=duration
        )

    def fit_bounds(
        self,
        bounds: List[float],
        padding: int = 50,
        duration: int = 1000,
    ) -> None:
        """Fit the map to bounds.

        Args:
            bounds: Bounds as [minLng, minLat, maxLng, maxLat].
            padding: Padding in pixels.
            duration: Animation duration in milliseconds.
        """
        self.call_js_method("fitBounds", bounds, padding=padding, duration=duration)

    def fit_extent(
        self,
        extent: List[float],
        padding: int = 50,
        duration: int = 1000,
    ) -> None:
        """Fit the map to an extent (in map projection).

        Args:
            extent: Extent as [minX, minY, maxX, maxY] in map projection.
            padding: Padding in pixels.
            duration: Animation duration in milliseconds.
        """
        self.call_js_method("fitExtent", extent, padding=padding, duration=duration)

    # -------------------------------------------------------------------------
    # Markers
    # -------------------------------------------------------------------------

    def add_marker(
        self,
        lng: float,
        lat: float,
        popup: Optional[str] = None,
        color: str = "#3388ff",
        name: Optional[str] = None,
        **kwargs,
    ) -> None:
        """Add a marker to the map.

        Args:
            lng: Marker longitude.
            lat: Marker latitude.
            popup: Popup content (HTML string).
            color: Marker color.
            name: Marker identifier.
            **kwargs: Additional options.
        """
        marker_id = name or f"marker-{len(self._layers)}"
        self.call_js_method(
            "addMarker",
            lng,
            lat,
            popup=popup,
            color=color,
            id=marker_id,
            **kwargs,
        )

    # -------------------------------------------------------------------------
    # HTML Export
    # -------------------------------------------------------------------------

    def _generate_html_template(self) -> str:
        """Generate standalone HTML for the map."""
        template_path = Path(__file__).parent / "templates" / "openlayers.html"

        if template_path.exists():
            template = template_path.read_text(encoding="utf-8")
        else:
            template = self._get_default_template()

        state = {
            "center": self.center,
            "zoom": self.zoom,
            "projection": self.projection,
            "rotation": self.rotation,
            "width": self.width,
            "height": self.height,
            "layers": self._layers,
            "controls": self._controls,
            "js_calls": self._js_calls,
        }

        template = template.replace("{{state}}", json.dumps(state, indent=2))
        return template

    def _get_default_template(self) -> str:
        """Get default HTML template."""
        return """<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>OpenLayers Map</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.0.0/ol.css">
    <script src="https://cdn.jsdelivr.net/npm/ol@v10.0.0/dist/ol.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        html, body { height: 100%; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
    </style>
</head>
<body>
    <div id="map"></div>
    <script>
        const state = {{state}};

        const map = new ol.Map({
            target: 'map',
            view: new ol.View({
                center: ol.proj.fromLonLat(state.center),
                zoom: state.zoom
            })
        });

        for (const call of state.js_calls || []) {
            executeMethod(call.method, call.args, call.kwargs);
        }

        function executeMethod(method, args, kwargs) {
            console.log('Executing:', method, args, kwargs);
        }
    </script>
</body>
</html>"""

__init__(self, center=(0.0, 0.0), zoom=2.0, width='100%', height='600px', projection='EPSG:3857', rotation=0.0, controls=None, **kwargs) special

Initialize an OpenLayers map.

Parameters:

Name Type Description Default
center Tuple[float, float]

Map center as (longitude, latitude).

(0.0, 0.0)
zoom float

Initial zoom level.

2.0
width str

Map width as CSS string.

'100%'
height str

Map height as CSS string.

'600px'
projection str

Map projection (default EPSG:3857).

'EPSG:3857'
rotation float

Map rotation in radians.

0.0
controls Optional[Dict[str, Any]]

Dict of controls to add.

None
**kwargs

Additional widget arguments.

{}
Source code in anymap_ts/openlayers.py
def __init__(
    self,
    center: Tuple[float, float] = (0.0, 0.0),
    zoom: float = 2.0,
    width: str = "100%",
    height: str = "600px",
    projection: str = "EPSG:3857",
    rotation: float = 0.0,
    controls: Optional[Dict[str, Any]] = None,
    **kwargs,
):
    """Initialize an OpenLayers map.

    Args:
        center: Map center as (longitude, latitude).
        zoom: Initial zoom level.
        width: Map width as CSS string.
        height: Map height as CSS string.
        projection: Map projection (default EPSG:3857).
        rotation: Map rotation in radians.
        controls: Dict of controls to add.
        **kwargs: Additional widget arguments.
    """
    super().__init__(
        center=list(center),
        zoom=zoom,
        width=width,
        height=height,
        projection=projection,
        rotation=rotation,
        **kwargs,
    )

    # Initialize layer dictionary
    self._layer_dict = {"Background": []}

    # Add default controls
    if controls is None:
        controls = {"zoom": True, "attribution": True}

    for control_name, config in controls.items():
        if config:
            self.add_control(
                control_name, **(config if isinstance(config, dict) else {})
            )

add_basemap(self, basemap='OpenStreetMap', attribution=None, **kwargs)

Add a basemap layer.

Parameters:

Name Type Description Default
basemap str

Name of basemap provider (e.g., "OpenStreetMap", "CartoDB.Positron").

'OpenStreetMap'
attribution Optional[str]

Custom attribution text.

None
**kwargs

Additional options.

{}
Source code in anymap_ts/openlayers.py
def add_basemap(
    self,
    basemap: str = "OpenStreetMap",
    attribution: Optional[str] = None,
    **kwargs,
) -> None:
    """Add a basemap layer.

    Args:
        basemap: Name of basemap provider (e.g., "OpenStreetMap", "CartoDB.Positron").
        attribution: Custom attribution text.
        **kwargs: Additional options.
    """
    url, default_attribution = get_basemap_url(basemap)
    self.call_js_method(
        "addBasemap",
        url,
        attribution=attribution or default_attribution,
        name=basemap,
        **kwargs,
    )

    basemaps = self._layer_dict.get("Basemaps", [])
    if basemap not in basemaps:
        self._layer_dict = {
            **self._layer_dict,
            "Basemaps": basemaps + [basemap],
        }

add_control(self, control_type, position='top-right', **kwargs)

Add a map control.

Parameters:

Name Type Description Default
control_type str

Type of control ('zoom', 'scale', 'fullscreen', etc.).

required
position str

Control position.

'top-right'
**kwargs

Control-specific options.

{}
Source code in anymap_ts/openlayers.py
def add_control(
    self,
    control_type: str,
    position: str = "top-right",
    **kwargs,
) -> None:
    """Add a map control.

    Args:
        control_type: Type of control ('zoom', 'scale', 'fullscreen', etc.).
        position: Control position.
        **kwargs: Control-specific options.
    """
    self.call_js_method("addControl", control_type, position=position, **kwargs)
    self._controls = {
        **self._controls,
        control_type: {"type": control_type, "position": position, **kwargs},
    }

add_geojson(self, data, name=None, style=None, fit_bounds=True, **kwargs)

Add GeoJSON data to the map.

Parameters:

Name Type Description Default
data Union[str, Dict]

GeoJSON dict or URL to GeoJSON file.

required
name Optional[str]

Layer name.

None
style Optional[Dict]

Style configuration dict.

None
fit_bounds bool

Whether to fit map to data bounds.

True
**kwargs

Additional layer options.

{}
Source code in anymap_ts/openlayers.py
def add_geojson(
    self,
    data: Union[str, Dict],
    name: Optional[str] = None,
    style: Optional[Dict] = None,
    fit_bounds: bool = True,
    **kwargs,
) -> None:
    """Add GeoJSON data to the map.

    Args:
        data: GeoJSON dict or URL to GeoJSON file.
        name: Layer name.
        style: Style configuration dict.
        fit_bounds: Whether to fit map to data bounds.
        **kwargs: Additional layer options.
    """
    self.add_vector(
        data,
        name=name,
        style=style,
        fit_bounds=fit_bounds,
        **kwargs,
    )

add_image_wms_layer(self, url, layers, name=None, format='image/png', transparent=True, server_type=None, attribution='', **kwargs)

Add a single-image WMS layer (not tiled).

Parameters:

Name Type Description Default
url str

WMS service URL.

required
layers str

Comma-separated layer names.

required
name Optional[str]

Layer name for the map.

None
format str

Image format (default: image/png).

'image/png'
transparent bool

Whether to request transparent images.

True
server_type Optional[str]

Server type ('mapserver', 'geoserver', 'qgis').

None
attribution str

Attribution text.

''
**kwargs

Additional WMS parameters.

{}
Source code in anymap_ts/openlayers.py
def add_image_wms_layer(
    self,
    url: str,
    layers: str,
    name: Optional[str] = None,
    format: str = "image/png",
    transparent: bool = True,
    server_type: Optional[str] = None,
    attribution: str = "",
    **kwargs,
) -> None:
    """Add a single-image WMS layer (not tiled).

    Args:
        url: WMS service URL.
        layers: Comma-separated layer names.
        name: Layer name for the map.
        format: Image format (default: image/png).
        transparent: Whether to request transparent images.
        server_type: Server type ('mapserver', 'geoserver', 'qgis').
        attribution: Attribution text.
        **kwargs: Additional WMS parameters.
    """
    layer_id = name or f"imagewms-{len(self._layers)}"

    self.call_js_method(
        "addImageWMSLayer",
        url=url,
        layers=layers,
        name=layer_id,
        format=format,
        transparent=transparent,
        serverType=server_type,
        attribution=attribution,
        **kwargs,
    )

    self._layers = {
        **self._layers,
        layer_id: {"id": layer_id, "type": "imagewms"},
    }

add_marker(self, lng, lat, popup=None, color='#3388ff', name=None, **kwargs)

Add a marker to the map.

Parameters:

Name Type Description Default
lng float

Marker longitude.

required
lat float

Marker latitude.

required
popup Optional[str]

Popup content (HTML string).

None
color str

Marker color.

'#3388ff'
name Optional[str]

Marker identifier.

None
**kwargs

Additional options.

{}
Source code in anymap_ts/openlayers.py
def add_marker(
    self,
    lng: float,
    lat: float,
    popup: Optional[str] = None,
    color: str = "#3388ff",
    name: Optional[str] = None,
    **kwargs,
) -> None:
    """Add a marker to the map.

    Args:
        lng: Marker longitude.
        lat: Marker latitude.
        popup: Popup content (HTML string).
        color: Marker color.
        name: Marker identifier.
        **kwargs: Additional options.
    """
    marker_id = name or f"marker-{len(self._layers)}"
    self.call_js_method(
        "addMarker",
        lng,
        lat,
        popup=popup,
        color=color,
        id=marker_id,
        **kwargs,
    )

add_tile_layer(self, url, name=None, attribution='', min_zoom=0, max_zoom=22, opacity=1.0, **kwargs)

Add an XYZ tile layer.

Parameters:

Name Type Description Default
url str

Tile URL template with {x}, {y}, {z} placeholders.

required
name Optional[str]

Layer name.

None
attribution str

Attribution text.

''
min_zoom int

Minimum zoom level.

0
max_zoom int

Maximum zoom level.

22
opacity float

Layer opacity.

1.0
**kwargs

Additional options.

{}
Source code in anymap_ts/openlayers.py
def add_tile_layer(
    self,
    url: str,
    name: Optional[str] = None,
    attribution: str = "",
    min_zoom: int = 0,
    max_zoom: int = 22,
    opacity: float = 1.0,
    **kwargs,
) -> None:
    """Add an XYZ tile layer.

    Args:
        url: Tile URL template with {x}, {y}, {z} placeholders.
        name: Layer name.
        attribution: Attribution text.
        min_zoom: Minimum zoom level.
        max_zoom: Maximum zoom level.
        opacity: Layer opacity.
        **kwargs: Additional options.
    """
    layer_id = name or f"tiles-{len(self._layers)}"

    self.call_js_method(
        "addTileLayer",
        url,
        name=layer_id,
        attribution=attribution,
        minZoom=min_zoom,
        maxZoom=max_zoom,
        opacity=opacity,
        **kwargs,
    )

    self._layers = {
        **self._layers,
        layer_id: {"id": layer_id, "type": "tile"},
    }

add_vector(self, data, name=None, style=None, fit_bounds=True, **kwargs)

Add vector data to the map.

Parameters:

Name Type Description Default
data Any

GeoJSON dict, GeoDataFrame, or path to vector file.

required
name Optional[str]

Layer name.

None
style Optional[Dict]

Style configuration dict.

None
fit_bounds bool

Whether to fit map to data bounds.

True
**kwargs

Additional layer options.

{}
Source code in anymap_ts/openlayers.py
def add_vector(
    self,
    data: Any,
    name: Optional[str] = None,
    style: Optional[Dict] = None,
    fit_bounds: bool = True,
    **kwargs,
) -> None:
    """Add vector data to the map.

    Args:
        data: GeoJSON dict, GeoDataFrame, or path to vector file.
        name: Layer name.
        style: Style configuration dict.
        fit_bounds: Whether to fit map to data bounds.
        **kwargs: Additional layer options.
    """
    geojson = to_geojson(data)
    layer_id = name or f"vector-{len(self._layers)}"

    if style is None:
        style = self._get_default_style(geojson)

    self.call_js_method(
        "addGeoJSON",
        data=geojson,
        name=layer_id,
        style=style,
        fitBounds=fit_bounds,
        **kwargs,
    )

    self._layers = {
        **self._layers,
        layer_id: {"id": layer_id, "type": "vector"},
    }

add_wms_layer(self, url, layers, name=None, format='image/png', transparent=True, server_type=None, attribution='', **kwargs)

Add a WMS tile layer.

Parameters:

Name Type Description Default
url str

WMS service URL.

required
layers str

Comma-separated layer names.

required
name Optional[str]

Layer name for the map.

None
format str

Image format (default: image/png).

'image/png'
transparent bool

Whether to request transparent images.

True
server_type Optional[str]

Server type ('mapserver', 'geoserver', 'qgis').

None
attribution str

Attribution text.

''
**kwargs

Additional WMS parameters.

{}
Source code in anymap_ts/openlayers.py
def add_wms_layer(
    self,
    url: str,
    layers: str,
    name: Optional[str] = None,
    format: str = "image/png",
    transparent: bool = True,
    server_type: Optional[str] = None,
    attribution: str = "",
    **kwargs,
) -> None:
    """Add a WMS tile layer.

    Args:
        url: WMS service URL.
        layers: Comma-separated layer names.
        name: Layer name for the map.
        format: Image format (default: image/png).
        transparent: Whether to request transparent images.
        server_type: Server type ('mapserver', 'geoserver', 'qgis').
        attribution: Attribution text.
        **kwargs: Additional WMS parameters.
    """
    layer_id = name or f"wms-{len(self._layers)}"

    self.call_js_method(
        "addWMSLayer",
        url=url,
        layers=layers,
        name=layer_id,
        format=format,
        transparent=transparent,
        serverType=server_type,
        attribution=attribution,
        **kwargs,
    )

    self._layers = {
        **self._layers,
        layer_id: {"id": layer_id, "type": "wms"},
    }

fit_bounds(self, bounds, padding=50, duration=1000)

Fit the map to bounds.

Parameters:

Name Type Description Default
bounds List[float]

Bounds as [minLng, minLat, maxLng, maxLat].

required
padding int

Padding in pixels.

50
duration int

Animation duration in milliseconds.

1000
Source code in anymap_ts/openlayers.py
def fit_bounds(
    self,
    bounds: List[float],
    padding: int = 50,
    duration: int = 1000,
) -> None:
    """Fit the map to bounds.

    Args:
        bounds: Bounds as [minLng, minLat, maxLng, maxLat].
        padding: Padding in pixels.
        duration: Animation duration in milliseconds.
    """
    self.call_js_method("fitBounds", bounds, padding=padding, duration=duration)

fit_extent(self, extent, padding=50, duration=1000)

Fit the map to an extent (in map projection).

Parameters:

Name Type Description Default
extent List[float]

Extent as [minX, minY, maxX, maxY] in map projection.

required
padding int

Padding in pixels.

50
duration int

Animation duration in milliseconds.

1000
Source code in anymap_ts/openlayers.py
def fit_extent(
    self,
    extent: List[float],
    padding: int = 50,
    duration: int = 1000,
) -> None:
    """Fit the map to an extent (in map projection).

    Args:
        extent: Extent as [minX, minY, maxX, maxY] in map projection.
        padding: Padding in pixels.
        duration: Animation duration in milliseconds.
    """
    self.call_js_method("fitExtent", extent, padding=padding, duration=duration)

fly_to(self, lng, lat, zoom=None, duration=2000)

Animate to a new location.

Parameters:

Name Type Description Default
lng float

Target longitude.

required
lat float

Target latitude.

required
zoom Optional[float]

Target zoom level (optional).

None
duration int

Animation duration in milliseconds.

2000
Source code in anymap_ts/openlayers.py
def fly_to(
    self,
    lng: float,
    lat: float,
    zoom: Optional[float] = None,
    duration: int = 2000,
) -> None:
    """Animate to a new location.

    Args:
        lng: Target longitude.
        lat: Target latitude.
        zoom: Target zoom level (optional).
        duration: Animation duration in milliseconds.
    """
    self.call_js_method(
        "flyTo", lng, lat, zoom=zoom or self.zoom, duration=duration
    )

remove_control(self, control_type)

Remove a map control.

Parameters:

Name Type Description Default
control_type str

Type of control to remove.

required
Source code in anymap_ts/openlayers.py
def remove_control(self, control_type: str) -> None:
    """Remove a map control.

    Args:
        control_type: Type of control to remove.
    """
    self.call_js_method("removeControl", control_type)
    if control_type in self._controls:
        controls = dict(self._controls)
        del controls[control_type]
        self._controls = controls

remove_layer(self, layer_id)

Remove a layer from the map.

Parameters:

Name Type Description Default
layer_id str

Layer identifier to remove.

required
Source code in anymap_ts/openlayers.py
def remove_layer(self, layer_id: str) -> None:
    """Remove a layer from the map.

    Args:
        layer_id: Layer identifier to remove.
    """
    if layer_id in self._layers:
        layers = dict(self._layers)
        del layers[layer_id]
        self._layers = layers
    self.call_js_method("removeLayer", layer_id)

set_center(self, lng, lat)

Set the map center.

Parameters:

Name Type Description Default
lng float

Longitude.

required
lat float

Latitude.

required
Source code in anymap_ts/openlayers.py
def set_center(self, lng: float, lat: float) -> None:
    """Set the map center.

    Args:
        lng: Longitude.
        lat: Latitude.
    """
    self.center = [lng, lat]
    self.call_js_method("setCenter", lng, lat)

set_opacity(self, layer_id, opacity)

Set layer opacity.

Parameters:

Name Type Description Default
layer_id str

Layer identifier.

required
opacity float

Opacity value between 0 and 1.

required
Source code in anymap_ts/openlayers.py
def set_opacity(self, layer_id: str, opacity: float) -> None:
    """Set layer opacity.

    Args:
        layer_id: Layer identifier.
        opacity: Opacity value between 0 and 1.
    """
    self.call_js_method("setOpacity", layer_id, opacity)

set_visibility(self, layer_id, visible)

Set layer visibility.

Parameters:

Name Type Description Default
layer_id str

Layer identifier.

required
visible bool

Whether layer should be visible.

required
Source code in anymap_ts/openlayers.py
def set_visibility(self, layer_id: str, visible: bool) -> None:
    """Set layer visibility.

    Args:
        layer_id: Layer identifier.
        visible: Whether layer should be visible.
    """
    self.call_js_method("setVisibility", layer_id, visible)

set_zoom(self, zoom)

Set the map zoom level.

Parameters:

Name Type Description Default
zoom float

Zoom level.

required
Source code in anymap_ts/openlayers.py
def set_zoom(self, zoom: float) -> None:
    """Set the map zoom level.

    Args:
        zoom: Zoom level.
    """
    self.zoom = zoom
    self.call_js_method("setZoom", zoom)