Support for Leaflet.markercluster? #2767
Replies: 3 comments
-
Hi @backbord, this looks like a really great extension to our Leaflet element! |
Beta Was this translation helpful? Give feedback.
-
I'm also interested in using leaflet plugins. I'm fairly new to this, but I believe the main hurdle is loading the plugin after leaflet but before the map is created. As a proof-of-principle, I modified Leaflet __init__ to take a list of additional resources to load, and then in leaflet.js, I load them in a similar manner to leaflet.draw. I also considered using a callback function or an event to allow more flexibility, but had trouble with those implementation details. This is the patch: diff --git a/nicegui/elements/leaflet.js b/nicegui/elements/leaflet.js
index 438af927..a20d8968 100644
--- a/nicegui/elements/leaflet.js
+++ b/nicegui/elements/leaflet.js
@@ -10,6 +10,7 @@ export default {
draw_control: Object,
resource_path: String,
hide_drawn_items: Boolean,
+ additional_resources: Array,
},
async mounted() {
await this.$nextTick(); // NOTE: wait for window.path_prefix to be set
@@ -23,6 +24,11 @@ export default {
loadResource(window.path_prefix + `${this.resource_path}/leaflet-draw/leaflet.draw.js`),
]);
}
+ // Load additional resources (leaflet plugins, etc)
+ var additionalResourcesLength = this.additional_resources.length;
+ for (var i = 0; additionalResourcesLength > i; ++i) {
+ await Promise.all([loadResource(this.additional_resources[i])]);
+ }
this.map = L.map(this.$el, {
...this.options,
center: this.center, diff --git a/nicegui/elements/leaflet.py b/nicegui/elements/leaflet.py
index 458e6d29..5174c22d 100644
--- a/nicegui/elements/leaflet.py
+++ b/nicegui/elements/leaflet.py
@@ -27,6 +27,7 @@ class Leaflet(Element, component='leaflet.js', default_classes='nicegui-leaflet'
options: Dict = {}, # noqa: B006
draw_control: Union[bool, Dict] = False,
hide_drawn_items: bool = False,
+ additional_resources: list[str] = [],
) -> None:
"""Leaflet map
@@ -51,6 +52,7 @@ class Leaflet(Element, component='leaflet.js', default_classes='nicegui-leaflet'
self._props['options'] = {**options}
self._props['draw_control'] = draw_control
self._props['hide_drawn_items'] = hide_drawn_items
+ self._props['additional_resources'] = additional_resources
self.on('init', self._handle_init)
self.on('map-moveend', self._handle_moveend) I tested it using the leaflet-contextmenu plugin, with the following setup. Context menus should work for both the map and the marker: from nicegui import app, ui
m = ui.leaflet(center=(51.51, -0.11),
options = {
'contextmenu': True,
'contextmenuItems': [{
'text': 'Show coordinates'
}]},
additional_resources = [
'https://cdnjs.cloudflare.com/ajax/libs/leaflet-contextmenu/1.4.0/leaflet.contextmenu.min.css',
'https://cdnjs.cloudflare.com/ajax/libs/leaflet-contextmenu/1.4.0/leaflet.contextmenu.min.js'])
m.marker(latlng=(51.51, -0.11),
options = {
'contextmenu': True,
'contextmenuItems': [{
'text': 'Marker Item'
}]})
ui.run() |
Beta Was this translation helpful? Give feedback.
-
I'm adding working examples for markerCluster (from original post and 2930), and extraMarkers and rotatedMarker (from 2795). Would it be possible to get something like this added to nicegui? # Import necessary methods
from nicegui import ui
from fastapi.responses import JSONResponse
# Endpoint to fetch JSON data with pin locations from
@ui.page("/api")
def ui_api():
return JSONResponse(content={
"pins": [
{"text": "asd", "lat": 50, "lng": 10},
{"text": "sdf", "lat": 51, "lng": 11},
{"text": "dfg", "lat": 49, "lng": 9}
]
})
# Index page that shows the map
@ui.page("/")
async def ui_index():
# Load respective CSS / JS files to include the MarkerCluster resources and Axios
ui.add_head_html("""<script src="https://unpkg.com/axios/dist/axios.min.js"></script>""")
# Create a UI element that's being used to render the map within
ui.label("Leaflet MarkerCluster with NiceGUI").classes("ml-auto mr-auto text-2xl font-bold")
m: ui.leaflet = ui.leaflet(center=(50, 10), zoom=6,
additional_resources = [
"https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css",
"https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css",
"https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"])
m.tile_layer(
url_template='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
options={
'maxZoom': 19,
'attribution': '© OpenStreetMap'
},
)
await m.initialized()
# Initialize the map and load the data from the API
map_fstr: str = f"var map = getElement({m.id}).map;"
ui.run_javascript(map_fstr + """let markers = L.markerClusterGroup();
function loadData() {
axios.get('/api')
.then(function (response) {
var pins = response.data.pins;
pins.forEach(function(pin) {
var marker = L.marker([pin.lat, pin.lng])
.bindPopup(pin.text);
markers.addLayer(marker);
});
map.addLayer(markers);
})
.catch(function (error) {
console.error('Error loading the pins:', error);
});
}
loadData();""")
ui.run(port=7777) # Import necessary methods
from nicegui import ui
# Index page that shows the map
@ui.page("/")
async def ui_index():
m: ui.leaflet = ui.leaflet(center=(51.505, -0.09),
additional_resources = [
"https://cdnjs.cloudflare.com/ajax/libs/leaflet-extra-markers/1.2.2/css/leaflet.extra-markers.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/leaflet-extra-markers/1.2.2/js/leaflet.extra-markers.min.js"
])
await m.initialized()
# Create a red marker with the coffee icon
map_fstr: str = f"var map = getElement({m.id}).map;"
ui.run_javascript(map_fstr + """
var redMarker = L.ExtraMarkers.icon({
icon: 'fa-coffee',
markerColor: 'red',
shape: 'square',
prefix: 'fa'
});
L.marker([51.51, -0.09], {icon: redMarker}).addTo(map);
""")
ui.run() # Import necessary methods
from nicegui import ui
# Index page that shows the map
@ui.page("/")
async def ui_index():
m: ui.leaflet = ui.leaflet(center=(51.505, -0.09),
additional_resources = [
"https://unpkg.com/[email protected]/leaflet.rotatedMarker.js",
])
await m.initialized()
# Create a rotated marker
map_fstr: str = f"var map = getElement({m.id}).map;"
ui.run_javascript(map_fstr + """
L.marker([51.51, -0.09], {rotationAngle: 45}).addTo(map);
""")
ui.run() |
Beta Was this translation helpful? Give feedback.
-
Hi!
I really like NiceGUI and the Leaflet integration. However, I'm not sure how to include and use Leaflet.markercluster.
Could you show me where to look or consider adding Leaflet.markercluster to NiceGUI?
Thanks in advance!
Beta Was this translation helpful? Give feedback.
All reactions