Skip to content

Commit 225376e

Browse files
committed
feat: useLMarkerCluster returns created layers + add popup as prop
1 parent 56d8e89 commit 225376e

File tree

4 files changed

+177
-38
lines changed

4 files changed

+177
-38
lines changed

docs/guide/marker-cluster.md

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
The guide explains how to use the [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster) plugin.
44
A dedicated composable is available to help you use this plugin.
55

6-
Options for the markers are the same as the ones available in the [Leaflet documentation](https://leafletjs.com/reference.html#marker).
7-
86
::: warning
97
This is only possible in a client-side environment. You should either :
108
- Use a [Client-Only Page](https://nuxt.com/docs/guide/directory-structure/pages#client-only-pages).
@@ -37,7 +35,7 @@ export default defineNuxtConfig({
3735
It is very important to keep the manual import of Leaflet and the `:use-global-leaflet="true"` as leaflet.markercluster requires Leaflet to be loaded globally.
3836
:::
3937

40-
```vue{9,23,28-61,65-68}
38+
```vue{9,23,28-50,54-57}
4139
<template>
4240
<div style="height:100vh; width:100vw">
4341
<h1>Marker Cluster</h1>
@@ -67,19 +65,8 @@ const map = ref(null) as any;
6765
6866
// Create locations data (20 locations around Nantes)
6967
const locations = [
70-
{ name: 'Nantes', lat: 47.218371, lng: -1.553621, options: {
71-
// Standard Leaflet Marker options
72-
draggable: true,
73-
icon: L.icon({
74-
iconUrl: '/my-icon.png',
75-
iconSize: [30, 30],
76-
})
77-
} },
78-
{
79-
// name is optional (no tooltip will be displayed if not provided)
80-
/* name: 'Saint-Nazaire', */
81-
lat: 47.273018, lng: -2.213733
82-
},
68+
{ name: 'Nantes', lat: 47.218371, lng: -1.553621 },
69+
{ name: 'Saint-Nazaire', lat: 47.273018, lng: -2.213733 },
8370
{ name: 'La Baule', lat: 47.286835, lng: -2.393108 },
8471
{ name: 'Pornic', lat: 47.112, lng: -2.102 },
8572
{ name: 'Guérande', lat: 47.328, lng: -2.429 },
@@ -109,3 +96,98 @@ const onMapReady = () => {
10996
}
11097
</script>
11198
```
99+
100+
## Options
101+
102+
Here are the options available for each marker in the `markers` prop.
103+
104+
| Event name | Type | Description |
105+
| ---------- | ------ | ------------------------------------------------------------------------------------------------------------------ |
106+
| name | string | **(optional)** Name of the location, will be displayed in a tooltip. If not provided, no tooltip will be displayed |
107+
| lat | number | Latitude of the location |
108+
| lng | number | Longitude of the location |
109+
| options | object | **(optional)** Standard [Leaflet Marker options](https://leafletjs.com/reference.html#marker) |
110+
| popup | string | **(optional)** If provided, it is considered as an HTML string and will be displayed as a popup on the marker |
111+
112+
## Recipes
113+
114+
### Accessing the cluster group
115+
116+
You can access the cluster group created by `useLMarkerCluster` to call any method from the [leaflet.markercluster API](https://github.com/Leaflet/Leaflet.markercluster?tab=readme-ov-file#events).
117+
118+
```ts
119+
const locations = [{
120+
name: 'Nantes',
121+
lat: 47.218371,
122+
lng: -1.553621
123+
}];
124+
const { markerCluster } = useLMarkerCluster({
125+
leafletObject: map.value.leafletObject,
126+
markers: locations
127+
});
128+
markerCluster.on('clusterclick', (event) => {
129+
console.log('Cluster clicked');
130+
});
131+
```
132+
133+
### Customizing the markers
134+
135+
You can use a customize the markers by providing the `icon` option in the location object.
136+
137+
```ts
138+
const locations = [{
139+
name: 'Nantes',
140+
lat: 47.218371,
141+
lng: -1.553621,
142+
options: {
143+
draggable: true,
144+
icon: L.icon({
145+
iconUrl: '/my-icon.png',
146+
iconSize: [30, 30],
147+
})
148+
}
149+
}];
150+
151+
useLMarkerCluster({
152+
leafletObject: map.value.leafletObject,
153+
markers: locations
154+
});
155+
```
156+
157+
### Displaying a popup on a marker
158+
159+
You can add a popup to a marker by providing the `popup` option in the location object.
160+
161+
```ts
162+
const locations = [{
163+
name: 'Nantes',
164+
lat: 47.218371,
165+
lng: -1.553621,
166+
popup: '<h1>This is Nantes</h1>'
167+
}];
168+
169+
useLMarkerCluster({
170+
leafletObject: map.value.leafletObject,
171+
markers: locations
172+
});
173+
```
174+
175+
### Calling legacy methods from Leaflet
176+
177+
You can access the markers created by `useLMarkerCluster`, and call any method from the [Leaflet Marker API](https://leafletjs.com/reference.html#marker).
178+
179+
```ts
180+
const locations = [{
181+
name: 'Nantes',
182+
lat: 47.218371,
183+
lng: -1.553621
184+
}];
185+
186+
const { markers } = useLMarkerCluster({
187+
leafletObject: map.value.leafletObject,
188+
markers: locations
189+
});
190+
markers.forEach(marker => {
191+
marker.bindPopup(L.popup().setContent('</h1>Hello marker</h1>'));
192+
});
193+
```

playground/pages/map/markercluster.client.vue

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,32 @@ const map = ref(null) as any;
2727
2828
// Create locations data (20 locations around Nantes)
2929
const locations = [
30-
{ name: 'Nantes', lat: 47.218371, lng: -1.553621, options: {
30+
{
31+
name: 'Nantes',
32+
lat: 47.218371,
33+
lng: -1.553621,
3134
// Standard Leaflet Marker options
32-
draggable: true,
33-
icon: L.icon({
34-
iconUrl: '/nuxt-leaflet-logo.png',
35-
iconSize: [30, 30],
36-
})
37-
} },
35+
options: {
36+
draggable: true,
37+
icon: L.icon({
38+
iconUrl: '/nuxt-leaflet-logo.png',
39+
iconSize: [30, 30],
40+
})
41+
}
42+
},
3843
{
3944
// name is optional (no tooltip will be displayed if not provided)
4045
/* name: 'Saint-Nazaire', */
41-
lat: 47.273018, lng: -2.213733
46+
lat: 47.273018, lng: -2.213733
47+
},
48+
{
49+
name: 'La Baule',
50+
lat: 47.286835,
51+
lng: -2.393108,
52+
// A popup can be displayed when clicking on the marker
53+
// It should be a string formatted as HTML
54+
popup: 'La Baule'
4255
},
43-
{ name: 'La Baule', lat: 47.286835, lng: -2.393108 },
4456
{ name: 'Pornic', lat: 47.112, lng: -2.102 },
4557
{ name: 'Guérande', lat: 47.328, lng: -2.429 },
4658
{ name: 'Clisson', lat: 47.087, lng: -1.276 },
@@ -61,10 +73,16 @@ const locations = [
6173
];
6274
6375
// When the map is ready
64-
const onMapReady = () => {
65-
useLMarkerCluster({
76+
const onMapReady = async () => {
77+
const { markers, markerCluster } = await useLMarkerCluster({
6678
leafletObject: map.value.leafletObject,
6779
markers: locations
6880
});
81+
// Access the markers
82+
markers[3].bindPopup('Hello Pornic');
83+
// Access the markerCluster
84+
markerCluster.on('clusterclick', (event: any) => {
85+
console.log('Cluster clicked', event);
86+
});
6987
}
7088
</script>

src/runtime/composables/useLMarkerCluster.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import type { MarkerOptions, Map } from 'leaflet'
1+
import type { MarkerOptions, Map, Marker } from 'leaflet'
22

33
interface MarkerProps {
44
name?: string
55
lat: number
66
lng: number
77
options?: MarkerOptions
8+
/**
9+
* Should be a string formatted as HTML
10+
*/
11+
popup?: string
812
}
913

1014
interface Props {
@@ -23,6 +27,9 @@ export const useLMarkerCluster = async (props: Props) => {
2327
// Initialize marker cluster
2428
const markerCluster = new MarkerClusterGroup()
2529

30+
// Create an array to store the markers
31+
const markers = [] as Marker[]
32+
2633
// For each marker in props
2734
props.markers.forEach((location: any) => {
2835
// Create a Leaflet marker
@@ -31,10 +38,24 @@ export const useLMarkerCluster = async (props: Props) => {
3138
...location.options,
3239
})
3340

41+
// If a popup is provided, bind it to the marker
42+
if (location.popup) {
43+
marker.bindPopup(L.popup().setContent(location.popup))
44+
}
45+
3446
// Add the marker to the cluster
3547
markerCluster.addLayer(marker)
48+
49+
// Add the marker to the markers array
50+
markers.push(marker)
3651
})
3752

3853
// Add the marker cluster to the map
3954
props.leafletObject.addLayer(markerCluster)
55+
56+
// Return the markerCluster and markers
57+
return {
58+
markerCluster,
59+
markers,
60+
}
4061
}

test/fixtures/markercluster/app.vue

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,32 @@ const map = ref(null) as any
2727
2828
// Create locations data (20 locations around Nantes)
2929
const locations = [
30-
{ name: 'Nantes', lat: 47.218371, lng: -1.553621, options: {
30+
{
31+
name: 'Nantes',
32+
lat: 47.218371,
33+
lng: -1.553621,
3134
// Standard Leaflet Marker options
32-
draggable: true,
33-
icon: L.icon({
34-
iconUrl: '/nuxt-leaflet-logo.png',
35-
iconSize: [30, 30],
36-
}),
37-
} },
35+
options: {
36+
draggable: true,
37+
icon: L.icon({
38+
iconUrl: '/nuxt-leaflet-logo.png',
39+
iconSize: [30, 30],
40+
}),
41+
},
42+
},
3843
{
3944
// name is optional (no tooltip will be displayed if not provided)
4045
/* name: 'Saint-Nazaire', */
4146
lat: 47.273018, lng: -2.213733,
4247
},
43-
{ name: 'La Baule', lat: 47.286835, lng: -2.393108 },
48+
{
49+
name: 'La Baule',
50+
lat: 47.286835,
51+
lng: -2.393108,
52+
// A popup can be displayed when clicking on the marker
53+
// It should be a string formatted as HTML
54+
popup: 'La Baule',
55+
},
4456
{ name: 'Pornic', lat: 47.112, lng: -2.102 },
4557
{ name: 'Guérande', lat: 47.328, lng: -2.429 },
4658
{ name: 'Clisson', lat: 47.087, lng: -1.276 },
@@ -61,10 +73,16 @@ const locations = [
6173
]
6274
6375
// When the map is ready
64-
const onMapReady = () => {
65-
useLMarkerCluster({
76+
const onMapReady = async () => {
77+
const { markers, markerCluster } = await useLMarkerCluster({
6678
leafletObject: map.value.leafletObject,
6779
markers: locations,
6880
})
81+
// Access the markers
82+
markers[3].bindPopup('Hello Pornic')
83+
// Access the markerCluster
84+
markerCluster.on('clusterclick', (event: any) => {
85+
console.log('Cluster clicked', event)
86+
})
6987
}
7088
</script>

0 commit comments

Comments
 (0)