Explorar o código

Image and Video Overlays in Leaflet API (#4707)

Fix #4686 and enables native usage of Image and Video Overlays in
Leaflet API, without resorting to `m.generic_layer`

Change in `leaflet.py` and `leaflet_layers.py` should be easy to
understand. Heck, they are written by GitHub copilot in full, after I
type a single character.

Notable details:
- Documentation aims to recreate the Leaflet demos 1:1
- Required a CSS tweak to make the video show up
- SVGOverlay not working, despite my best efforts (dumped 2 hours into
it), so was not included.

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
Evan Chan hai 1 semana
pai
achega
096adcc54a

+ 2 - 0
nicegui/elements/leaflet.py

@@ -14,8 +14,10 @@ from .leaflet_layer import Layer
 class Leaflet(Element, component='leaflet.js', default_classes='nicegui-leaflet'):
     # pylint: disable=import-outside-toplevel
     from .leaflet_layers import GenericLayer as generic_layer
+    from .leaflet_layers import ImageOverlay as image_overlay
     from .leaflet_layers import Marker as marker
     from .leaflet_layers import TileLayer as tile_layer
+    from .leaflet_layers import VideoOverlay as video_overlay
     from .leaflet_layers import WmsLayer as wms_layer
 
     center = binding.BindableProperty(lambda sender, value: cast(Leaflet, sender).set_center(value))

+ 27 - 1
nicegui/elements/leaflet_layers.py

@@ -1,5 +1,5 @@
 from dataclasses import dataclass, field
-from typing import Any, Dict, List, Tuple
+from typing import Any, Dict, List, Tuple, Union
 
 from typing_extensions import Self
 
@@ -43,6 +43,32 @@ class WmsLayer(Layer):
         }
 
 
+@dataclass(**KWONLY_SLOTS)
+class ImageOverlay(Layer):
+    url: str
+    bounds: List[List[float]]
+    options: Dict = field(default_factory=dict)
+
+    def to_dict(self) -> Dict:
+        return {
+            'type': 'imageOverlay',
+            'args': [self.url, self.bounds, self.options],
+        }
+
+
+@dataclass(**KWONLY_SLOTS)
+class VideoOverlay(Layer):
+    url: Union[str, List[str]]
+    bounds: List[List[float]]
+    options: Dict = field(default_factory=dict)
+
+    def to_dict(self) -> Dict:
+        return {
+            'type': 'videoOverlay',
+            'args': [self.url, self.bounds, self.options],
+        }
+
+
 @dataclass(**KWONLY_SLOTS)
 class Marker(Layer):
     latlng: Tuple[float, float]

+ 3 - 0
nicegui/static/nicegui.css

@@ -219,6 +219,9 @@
   width: 100%;
   height: 16rem;
 }
+.nicegui-leaflet video.leaflet-image-layer {
+  max-width: none; /* HACK: make the video show up */
+}
 .nicegui-log {
   padding: 0.5rem;
   scroll-padding-bottom: 0.5rem;

+ 26 - 0
website/documentation/content/leaflet_documentation.py

@@ -77,6 +77,32 @@ def move_markers() -> None:
     ui.button('Move marker', on_click=lambda: marker.move(51.51, -0.09))
 
 
+@doc.demo('Image Overlays', '''
+    Leaflet supports [image overlays](https://leafletjs.com/reference.html#imageoverlay).
+    You can add an image overlay with the `image_overlay` method.
+''')
+def overlay_image():
+    m = ui.leaflet(center=(40.74, -74.18), zoom=11)
+    m.image_overlay(
+        url='https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
+        bounds=[[40.712216, -74.22655], [40.773941, -74.12544]],
+        options={'opacity': 0.8},
+    )
+
+
+@doc.demo('Video Overlays', '''
+    Leaflet supports [video overlays](https://leafletjs.com/reference.html#videooverlay).
+    You can add a video overlay with the `video_overlay` method.
+''')
+def overlay_video():
+    m = ui.leaflet(center=(23.0, -115.0), zoom=3)
+    m.video_overlay(
+        url='https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+        bounds=[[32, -130], [13, -100]],
+        options={'opacity': 0.8, 'autoplay': True, 'playsInline': True},
+    )
+
+
 @doc.demo('Vector Layers', '''
     Leaflet supports a set of [vector layers](https://leafletjs.com/reference.html#:~:text=VideoOverlay-,Vector%20Layers,-Path) like circle, polygon etc.
     These can be added with the `generic_layer` method.