From b8feb3d205c4d2d55c84578f145078adbd840893 Mon Sep 17 00:00:00 2001 From: Jt Miclat Date: Wed, 27 Sep 2023 13:54:36 +0800 Subject: [PATCH 1/3] Add style parsing using protomaps.json_style to PMTilesVectorLayer. Rename PMTilesVectorBasemap to PMTilesVectorLayer --- example/pmtiles_vector.ipynb | 60 ++++++++++++++++++++++++++++-------- folium_pmtiles/__init__.py | 2 +- folium_pmtiles/vector.py | 9 ++++-- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/example/pmtiles_vector.ipynb b/example/pmtiles_vector.ipynb index f42e95f..0f2c336 100644 --- a/example/pmtiles_vector.ipynb +++ b/example/pmtiles_vector.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -19,7 +19,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -52,7 +52,7 @@ " <meta name="viewport" content="width=device-width,\n", " initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />\n", " <style>\n", - " #map_e20173359702b82de5b022e539e27e17 {\n", + " #map_31eff136ccf0eae29ff8f2cf5f06c783 {\n", " position: relative;\n", " width: 100.0%;\n", " height: 100.0%;\n", @@ -67,14 +67,14 @@ "<body>\n", " \n", " \n", - " <div class="folium-map" id="map_e20173359702b82de5b022e539e27e17" ></div>\n", + " <div class="folium-map" id="map_31eff136ccf0eae29ff8f2cf5f06c783" ></div>\n", " \n", "</body>\n", "<script>\n", " \n", " \n", - " var map_e20173359702b82de5b022e539e27e17 = L.map(\n", - " "map_e20173359702b82de5b022e539e27e17",\n", + " var map_31eff136ccf0eae29ff8f2cf5f06c783 = L.map(\n", + " "map_31eff136ccf0eae29ff8f2cf5f06c783",\n", " {\n", " center: [43.7798, 11.24148],\n", " crs: L.CRS.EPSG3857,\n", @@ -87,21 +87,30 @@ " \n", "\n", " \n", - " var pm_tiles_vector_a732d086128705bed0d97eafe8c07672 = protomaps.leafletLayer(\n", + " \n", + " var tile_layer_38778874768e88de15485212026f9a34 = L.tileLayer(\n", + " "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",\n", + " {"attribution": "Data by \\u0026copy; \\u003ca target=\\"_blank\\" href=\\"http://openstreetmap.org\\"\\u003eOpenStreetMap\\u003c/a\\u003e, under \\u003ca target=\\"_blank\\" href=\\"http://www.openstreetmap.org/copyright\\"\\u003eODbL\\u003c/a\\u003e.", "detectRetina": false, "maxNativeZoom": 18, "maxZoom": 18, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}\n", + " ).addTo(map_31eff136ccf0eae29ff8f2cf5f06c783);\n", + " \n", + " var pm_tiles_vector_e740ed251d4b374e6191a7c2f923a73d = protomaps.leafletLayer(\n", " {\n", " "url": 'https://pmtiles.jtmiclat.me/protomaps(vector)ODbL_firenze.pmtiles',\n", + " \n", + " ...protomaps.json_style({"layers": [{"id": "landuse", "paint": {"fill-color": "steelblue"}, "source": "example_source", "source-layer": "landuse", "type": "fill"}, {"id": "roads", "paint": {"line-color": "black"}, "source": "example_source", "source-layer": "roads", "type": "line"}]}), \n", + " \n", " ...{"attribution": "\\u003ca href=\\"https://protomaps.com\\"\\u003eProtomaps\\u003c/a\\u003e \\u00a9 \\u003ca href=\\"https://openstreetmap.org/copyright\\"\\u003eOpenStreetMap\\u003c/a\\u003e\\u0027"}\n", " }\n", " )\n", - " pm_tiles_vector_a732d086128705bed0d97eafe8c07672.addTo(map_e20173359702b82de5b022e539e27e17)\n", + " pm_tiles_vector_e740ed251d4b374e6191a7c2f923a73d.addTo(map_31eff136ccf0eae29ff8f2cf5f06c783)\n", "</script>\n", "</html>\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen>" ], "text/plain": [ - "" + "" ] }, - "execution_count": 2, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -109,12 +118,30 @@ "source": [ "import folium\n", "\n", - "from folium_pmtiles.vector import PMTilesVectorBaseMap\n", + "from folium_pmtiles.vector import PMTilesVector\n", "\n", - "m = folium.Map(location=[43.7798, 11.24148], zoom_start=12, tiles=None)\n", - "pmtiles_layer = PMTilesVectorBaseMap(\n", + "m = folium.Map(location=[43.7798, 11.24148], zoom_start=12)\n", + "pmtiles_layer = PMTilesVector(\n", " \"https://pmtiles.jtmiclat.me/protomaps(vector)ODbL_firenze.pmtiles\",\n", " \"folium_layer_name\",\n", + " style={\n", + " \"layers\": [\n", + " {\n", + " \"id\": \"landuse\",\n", + " \"source\": \"example_source\",\n", + " \"source-layer\": \"landuse\",\n", + " \"type\": \"fill\",\n", + " \"paint\": {\"fill-color\": \"steelblue\"},\n", + " },\n", + " {\n", + " \"id\": \"roads\",\n", + " \"source\": \"example_source\",\n", + " \"source-layer\": \"roads\",\n", + " \"type\": \"line\",\n", + " \"paint\": {\"line-color\": \"black\"},\n", + " },\n", + " ],\n", + " },\n", " options={\n", " \"attribution\": \"\"\"Protomaps © OpenStreetMap'\"\"\"\n", " },\n", @@ -122,6 +149,13 @@ "m.add_child(pmtiles_layer)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/folium_pmtiles/__init__.py b/folium_pmtiles/__init__.py index 6100f24..ca2e8fe 100644 --- a/folium_pmtiles/__init__.py +++ b/folium_pmtiles/__init__.py @@ -1,2 +1,2 @@ from .raster import PMTilesRaster # noqa -from .vector import PMTilesMapLibreLayer, PMTilesVectorBaseMap # noqa +from .vector import PMTilesMapLibreLayer, PMTilesVector # noqa diff --git a/folium_pmtiles/vector.py b/folium_pmtiles/vector.py index 16edb78..77cb16e 100644 --- a/folium_pmtiles/vector.py +++ b/folium_pmtiles/vector.py @@ -3,7 +3,7 @@ from jinja2 import Template -class PMTilesVectorBaseMap(JSCSSMixin, Layer): +class PMTilesVector(JSCSSMixin, Layer): """Based of https://github.com/python-visualization/folium/blob/56d3665fdc9e7280eae1df1262450e53ec4f5a60/folium/plugins/vectorgrid_protobuf.py """ @@ -16,6 +16,9 @@ class PMTilesVectorBaseMap(JSCSSMixin, Layer): var {{ this.get_name() }} = protomaps.leafletLayer( { "url": '{{ this.url }}', + {% if this.style %} + ...protomaps.json_style({{ this.style|tojson}}), + {% endif %} ...{{ this.options if this.options is string else this.options|tojson }} } ) @@ -31,13 +34,15 @@ class PMTilesVectorBaseMap(JSCSSMixin, Layer): ) ] - def __init__(self, url, layer_name=None, options=None, **kwargs): + def __init__(self, url, layer_name=None, style=None, options=None, **kwargs): self.layer_name = layer_name if layer_name else "PMTilesVector" super().__init__(name=self.layer_name, **kwargs) self.url = url self._name = "PMTilesVector" + if style is not None: + self.style = style if options is not None: self.options = options From ce33b634014453274dbcc14e67aebad640709054 Mon Sep 17 00:00:00 2001 From: Jt Miclat Date: Wed, 27 Sep 2023 13:58:50 +0800 Subject: [PATCH 2/3] Migrate to protomaps-leaflet --- example/pmtiles_vector.ipynb | 30 +++++++++++++----------------- folium_pmtiles/vector.py | 8 ++++---- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/example/pmtiles_vector.ipynb b/example/pmtiles_vector.ipynb index 0f2c336..8c9cc24 100644 --- a/example/pmtiles_vector.ipynb +++ b/example/pmtiles_vector.ipynb @@ -19,7 +19,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -52,7 +52,7 @@ " <meta name="viewport" content="width=device-width,\n", " initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />\n", " <style>\n", - " #map_31eff136ccf0eae29ff8f2cf5f06c783 {\n", + " #map_95466bd0ff7c1a81394c79573fd27a8b {\n", " position: relative;\n", " width: 100.0%;\n", " height: 100.0%;\n", @@ -62,19 +62,19 @@ " .leaflet-container { font-size: 1rem; }\n", " </style>\n", " \n", - " <script src="https://unpkg.com/protomaps@1.23.0/dist/protomaps.min.js"></script>\n", + " <script src="https://unpkg.com/protomaps-leaflet@1.24.0/dist/protomaps-leaflet.min.js"></script>\n", "</head>\n", "<body>\n", " \n", " \n", - " <div class="folium-map" id="map_31eff136ccf0eae29ff8f2cf5f06c783" ></div>\n", + " <div class="folium-map" id="map_95466bd0ff7c1a81394c79573fd27a8b" ></div>\n", " \n", "</body>\n", "<script>\n", " \n", " \n", - " var map_31eff136ccf0eae29ff8f2cf5f06c783 = L.map(\n", - " "map_31eff136ccf0eae29ff8f2cf5f06c783",\n", + " var map_95466bd0ff7c1a81394c79573fd27a8b = L.map(\n", + " "map_95466bd0ff7c1a81394c79573fd27a8b",\n", " {\n", " center: [43.7798, 11.24148],\n", " crs: L.CRS.EPSG3857,\n", @@ -88,29 +88,29 @@ "\n", " \n", " \n", - " var tile_layer_38778874768e88de15485212026f9a34 = L.tileLayer(\n", + " var tile_layer_734741ed77573dcba34adec617ba10f9 = L.tileLayer(\n", " "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",\n", " {"attribution": "Data by \\u0026copy; \\u003ca target=\\"_blank\\" href=\\"http://openstreetmap.org\\"\\u003eOpenStreetMap\\u003c/a\\u003e, under \\u003ca target=\\"_blank\\" href=\\"http://www.openstreetmap.org/copyright\\"\\u003eODbL\\u003c/a\\u003e.", "detectRetina": false, "maxNativeZoom": 18, "maxZoom": 18, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}\n", - " ).addTo(map_31eff136ccf0eae29ff8f2cf5f06c783);\n", + " ).addTo(map_95466bd0ff7c1a81394c79573fd27a8b);\n", " \n", - " var pm_tiles_vector_e740ed251d4b374e6191a7c2f923a73d = protomaps.leafletLayer(\n", + " var pm_tiles_vector_38808b3c87e8ccf7757edd7551bc90c6 = protomapsL.leafletLayer(\n", " {\n", " "url": 'https://pmtiles.jtmiclat.me/protomaps(vector)ODbL_firenze.pmtiles',\n", " \n", - " ...protomaps.json_style({"layers": [{"id": "landuse", "paint": {"fill-color": "steelblue"}, "source": "example_source", "source-layer": "landuse", "type": "fill"}, {"id": "roads", "paint": {"line-color": "black"}, "source": "example_source", "source-layer": "roads", "type": "line"}]}), \n", + " ...protomapsL.json_style({"layers": [{"paint": {"fill-color": "steelblue"}, "source-layer": "landuse", "type": "fill"}, {"paint": {"line-color": "black"}, "source-layer": "roads", "type": "line"}]}), \n", " \n", " ...{"attribution": "\\u003ca href=\\"https://protomaps.com\\"\\u003eProtomaps\\u003c/a\\u003e \\u00a9 \\u003ca href=\\"https://openstreetmap.org/copyright\\"\\u003eOpenStreetMap\\u003c/a\\u003e\\u0027"}\n", " }\n", " )\n", - " pm_tiles_vector_e740ed251d4b374e6191a7c2f923a73d.addTo(map_31eff136ccf0eae29ff8f2cf5f06c783)\n", + " pm_tiles_vector_38808b3c87e8ccf7757edd7551bc90c6.addTo(map_95466bd0ff7c1a81394c79573fd27a8b)\n", "</script>\n", "</html>\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen>" ], "text/plain": [ - "" + "" ] }, - "execution_count": 1, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -127,15 +127,11 @@ " style={\n", " \"layers\": [\n", " {\n", - " \"id\": \"landuse\",\n", - " \"source\": \"example_source\",\n", " \"source-layer\": \"landuse\",\n", " \"type\": \"fill\",\n", " \"paint\": {\"fill-color\": \"steelblue\"},\n", " },\n", " {\n", - " \"id\": \"roads\",\n", - " \"source\": \"example_source\",\n", " \"source-layer\": \"roads\",\n", " \"type\": \"line\",\n", " \"paint\": {\"line-color\": \"black\"},\n", diff --git a/folium_pmtiles/vector.py b/folium_pmtiles/vector.py index 77cb16e..2d44ac5 100644 --- a/folium_pmtiles/vector.py +++ b/folium_pmtiles/vector.py @@ -13,11 +13,11 @@ class PMTilesVector(JSCSSMixin, Layer): {% macro script(this, kwargs) -%} - var {{ this.get_name() }} = protomaps.leafletLayer( + var {{ this.get_name() }} = protomapsL.leafletLayer( { "url": '{{ this.url }}', {% if this.style %} - ...protomaps.json_style({{ this.style|tojson}}), + ...protomapsL.json_style({{ this.style|tojson}}), {% endif %} ...{{ this.options if this.options is string else this.options|tojson }} } @@ -29,8 +29,8 @@ class PMTilesVector(JSCSSMixin, Layer): default_js = [ ( - "protomaps", - "https://unpkg.com/protomaps@1.23.0/dist/protomaps.min.js", + "protomapsL", + "https://unpkg.com/protomaps-leaflet@1.24.0/dist/protomaps-leaflet.min.js", ) ] From 9334cfa631932c07ffa7e90b9e2e66be4de6f32b Mon Sep 17 00:00:00 2001 From: Jt Miclat Date: Wed, 27 Sep 2023 14:02:14 +0800 Subject: [PATCH 3/3] Update readme with suggestions --- README.md | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index e3ae382..baaf47a 100644 --- a/README.md +++ b/README.md @@ -10,45 +10,37 @@ pip install folium folium-pmtiles ### Usage -The recommend way is to use `PMTilesMapLibreLayer`. This overlays a maplibre instance over leaflet which allows declarative styling using mapbox style specification. +The recommend way is to use `PMTilesVector`. This converts a simple mapbox style to a appropriate leaflet/protomaps styles. +If you need more complex styling, you can use `PMTilesMapLibreLayer` A simple folium example is as follows: ```python import folium -from folium_pmtiles.vector import PMTilesMapLibreLayer +from folium_pmtiles.vector import PMTilesVector -m = folium.Map(location=[43.7798, 11.24148], zoom_start=13, tiles="cartodb positron") -pmtiles_url = "https://pmtiles.jtmiclat.me/protomaps(vector)ODbL_firenze.pmtiles" -pmtiles_layer = PMTilesMapLibreLayer( +m = folium.Map(location=[43.7798, 11.24148], zoom_start=12) +pmtiles_layer = PMTilesVector( + "https://pmtiles.jtmiclat.me/protomaps(vector)ODbL_firenze.pmtiles", "folium_layer_name", style={ - "version": 8, - "sources": { - "example_source": { - "type": "vector", - "url": "pmtiles://" + pmtiles_url, - "attribution": 'Protomaps © OpenStreetMap', - } - }, "layers": [ { - "id": "buildings", - "source": "example_source", "source-layer": "landuse", "type": "fill", "paint": {"fill-color": "steelblue"}, }, { - "id": "roads", - "source": "example_source", "source-layer": "roads", "type": "line", "paint": {"line-color": "black"}, }, ], }, + options={ + "attribution": """Protomaps © OpenStreetMap'""" + }, ) m.add_child(pmtiles_layer) ```