From e893afc09da9157a364e8c2b2f9aa1e74e0945ee Mon Sep 17 00:00:00 2001 From: Qiusheng Wu Date: Thu, 20 Jun 2024 15:27:33 -0400 Subject: [PATCH] Add Map.rotate_to method --- docs/maplibre/overview.md | 12 ++ docs/maplibre/variable_label_placement.ipynb | 177 ++++++++++++++++++ .../visualize_population_density.ipynb | 54 +++++- leafmap/maplibregl.py | 21 +++ mkdocs.yml | 1 + 5 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 docs/maplibre/variable_label_placement.ipynb diff --git a/docs/maplibre/overview.md b/docs/maplibre/overview.md index 4364bcca6a..aa83b199bb 100644 --- a/docs/maplibre/overview.md +++ b/docs/maplibre/overview.md @@ -92,12 +92,24 @@ Initialize a map with pitch and bearing camera options. [![](https://i.imgur.com/onKRYXz.png)](https://leafmap.org/maplibre/set_pitch_bearing) +## Variable label placement with offset + +Use text-variable-anchor-offset to allow high priority labels to shift position to stay on the map. + +[![](https://i.imgur.com/HKfcsoc.png)](https://leafmap.org/maplibre/variable_label_placement) + ## Add a vector tile source Add a vector source to a map. [![](https://i.imgur.com/svfZwFh.jpeg)](https://leafmap.org/maplibre/vector_tile) +## Visualize population density + +Use a variable binding expression to calculate and display population density. + +[![](https://i.imgur.com/7qpnvOP.png)](https://leafmap.org/maplibre/visualize_population_density) + ## Add a WMS source Add an external Web Map Service raster layer to the map using addSource's tiles option. diff --git a/docs/maplibre/variable_label_placement.ipynb b/docs/maplibre/variable_label_placement.ipynb new file mode 100644 index 0000000000..8c81ade9c7 --- /dev/null +++ b/docs/maplibre/variable_label_placement.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://demo.leafmap.org/lab/index.html?path=maplibre/variable_label_placement.ipynb)\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/leafmap/blob/master/docs/maplibre/variable_label_placement.ipynb)\n", + "[![image](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/opengeos/leafmap/HEAD)\n", + "\n", + "**Variable label placement with offset**\n", + "\n", + "This source code of this example is adapted from the MapLibre GL JS example - [Variable label placement with offset](https://maplibre.org/maplibre-gl-js/docs/examples/variable-offset-label-placement).\n", + "\n", + "Uncomment the following line to install [leafmap](https://leafmap.org) if needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install \"leafmap[maplibre]\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import leafmap.maplibregl as leafmap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run this notebook, you will need an [API key](https://docs.maptiler.com/cloud/api/authentication-key/) from [MapTiler](https://www.maptiler.com/cloud/). Once you have the API key, you can set it as an environment variable in your notebook or script as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# os.environ[\"MAPTILER_KEY\"] = \"YOUR_API_KEY\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "MAPTILER_KEY = os.environ.get(\"MAPTILER_KEY\")\n", + "style = f\"https://api.maptiler.com/maps/streets/style.json?key={MAPTILER_KEY}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = leafmap.Map(center=[-77.04, 38.907], zoom=11, style=style)\n", + "\n", + "places = {\n", + " 'type': 'FeatureCollection',\n", + " 'features': [\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'Ford\\'s Theater', 'icon': 'theatre'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.038659, 38.931567]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'The Gaslight', 'icon': 'theatre'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.003168, 38.894651]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'Horrible Harry\\'s', 'icon': 'bar'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.090372, 38.881189]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'Bike Party', 'icon': 'bicycle'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.052477, 38.943951]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'Rockabilly Rockstars', 'icon': 'music'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.031706, 38.914581]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'District Drum Tribe', 'icon': 'music'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.020945, 38.878241]},\n", + " },\n", + " {\n", + " 'type': 'Feature',\n", + " 'properties': {'description': 'Motown Memories', 'icon': 'music'},\n", + " 'geometry': {'type': 'Point', 'coordinates': [-77.007481, 38.876516]},\n", + " },\n", + " ],\n", + "}\n", + "source = {'type': 'geojson', 'data': places}\n", + "m.add_source(\"places\", source)\n", + "\n", + "layer = {\n", + " 'id': 'poi-labels',\n", + " 'type': 'symbol',\n", + " 'source': 'places',\n", + " 'layout': {\n", + " 'text-field': ['get', 'description'],\n", + " 'text-variable-anchor-offset': [\n", + " 'top',\n", + " [0, 1],\n", + " 'bottom',\n", + " [0, -2],\n", + " 'left',\n", + " [1, 0],\n", + " 'right',\n", + " [-2, 0],\n", + " ],\n", + " 'text-justify': 'auto',\n", + " 'icon-image': ['concat', ['get', 'icon'], '_15'],\n", + " },\n", + "}\n", + "m.add_layer(layer)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.rotate_to(bearing=180, options={\"duration\": 10000})" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](https://i.imgur.com/HKfcsoc.png)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/maplibre/visualize_population_density.ipynb b/docs/maplibre/visualize_population_density.ipynb index cfd7991c00..37cf09b8e1 100644 --- a/docs/maplibre/visualize_population_density.ipynb +++ b/docs/maplibre/visualize_population_density.ipynb @@ -66,9 +66,61 @@ "metadata": {}, "outputs": [], "source": [ - "m = leafmap.Map(center=[-100, 40], zoom=3, style=style)\n", + "m = leafmap.Map(center=[30.0222, -1.9596], zoom=7, style=style)\n", + "source = {\n", + " \"type\": \"geojson\",\n", + " \"data\": \"https://maplibre.org/maplibre-gl-js/docs/assets/rwanda-provinces.geojson\",\n", + "}\n", + "m.add_source(\"rwanda-provinces\", source)\n", + "layer = {\n", + " \"id\": \"rwanda-provinces\",\n", + " \"type\": \"fill\",\n", + " \"source\": \"rwanda-provinces\",\n", + " \"layout\": {},\n", + " \"paint\": {\n", + " \"fill-color\": [\n", + " \"let\",\n", + " \"density\",\n", + " [\"/\", [\"get\", \"population\"], [\"get\", \"sq-km\"]],\n", + " [\n", + " \"interpolate\",\n", + " [\"linear\"],\n", + " [\"zoom\"],\n", + " 8,\n", + " [\n", + " \"interpolate\",\n", + " [\"linear\"],\n", + " [\"var\", \"density\"],\n", + " 274,\n", + " [\"to-color\", \"#edf8e9\"],\n", + " 1551,\n", + " [\"to-color\", \"#006d2c\"],\n", + " ],\n", + " 10,\n", + " [\n", + " \"interpolate\",\n", + " [\"linear\"],\n", + " [\"var\", \"density\"],\n", + " 274,\n", + " [\"to-color\", \"#eff3ff\"],\n", + " 1551,\n", + " [\"to-color\", \"#08519c\"],\n", + " ],\n", + " ],\n", + " ],\n", + " \"fill-opacity\": 0.7,\n", + " },\n", + "}\n", + "m.add_layer(layer)\n", "m" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](https://i.imgur.com/7qpnvOP.png)" + ] } ], "metadata": { diff --git a/leafmap/maplibregl.py b/leafmap/maplibregl.py index 19e530de18..7096c02bf6 100644 --- a/leafmap/maplibregl.py +++ b/leafmap/maplibregl.py @@ -1466,3 +1466,24 @@ def to_streamlit( except Exception as e: raise Exception(e) + + def rotate_to( + self, bearing: float, options: Dict[str, Any] = {}, **kwargs: Any + ) -> None: + """ + Rotate the map to a specified bearing. + + This function rotates the map to a specified bearing. The bearing is specified in degrees + counter-clockwise from true north. If the bearing is not specified, the map will rotate to + true north. Additional options and keyword arguments can be provided to control the rotation. + For more information, see https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#rotateto + + Args: + bearing (float): The bearing to rotate to, in degrees counter-clockwise from true north. + options (Dict[str, Any], optional): Additional options to control the rotation. Defaults to {}. + **kwargs (Any): Additional keyword arguments to control the rotation. + + Returns: + None + """ + super().add_call("rotateTo", bearing, options, **kwargs) diff --git a/mkdocs.yml b/mkdocs.yml index b13363c72e..dad50a0df2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -152,6 +152,7 @@ nav: - maplibre/geojson_line.ipynb - maplibre/satellite_map.ipynb - maplibre/set_pitch_bearing.ipynb + - maplibre/variable_label_placement.ipynb - maplibre/vector_tile.ipynb - maplibre/add_video.ipynb - maplibre/visualize_population_density.ipynb