Reputation: 21
I'm using Leaflet with Nuxt3, TypeScript and Composition API on a production website. As we're getting more and more markers, I'd like to use leaflet.markercluster but I can't get how to make it work properly
Here's my setup :
leaflet.client.ts
import {
LIcon,
LMap,
LMarker,
LPopup,
LTileLayer,
} from "@vue-leaflet/vue-leaflet";
import L from "leaflet";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("LMap", LMap);
nuxtApp.vueApp.component("LTileLayer", LTileLayer);
nuxtApp.vueApp.component("LMarker", LMarker);
nuxtApp.vueApp.component("LIcon", LIcon);
nuxtApp.vueApp.component("LPopup", LPopup);
return {
provide: {
L,
},
};
});
Map.vue
<client-only>
<l-map
ref="locationsMap"
:min-zoom="leafletOptions.minZoom"
:max-zoom="leafletOptions.maxZoom"
:zoom-animation="true"
:zoom="leafletOptions.zoom"
:center="leafletOptions.center"
:useGlobalLeaflet="false"
:options="{ tap: false }"
@ready="onLeafletReady">
<l-tile-layer :url="leafletOptions.url"/>
<template v-for="location in locations"
:key="location.id">
<l-marker
:lat-lng="[location.attributes.lat, location.attributes.long]"
v-if="location.attributes.active">
<div v-if="location.attributes.lat && location.attributes.long">
<l-popup class="text-center flex flex-col gap-y-4">
...
</l-popup>
<l-icon>
...
</l-icon>
</div>
</l-marker>
</template>
</l-map>
...
</client-only>
<script setup lang="ts">
import {LIcon, LMap, LMarker, LPopup, LTileLayer} from "@vue-leaflet/vue-leaflet";
import "leaflet/dist/leaflet.css";
const leafletOptions = ref({
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
minZoom: 5,
maxZoom: 13,
zoom: 5.5,
map: null,
center: [47.040182, 2.536054],
bounds: null,
overlayLocation: false,
colors: ["#ED722E", "#F6BE00", "#979B0B", "#DA2C81"],
});
// Setup and api calls to get locations
</script>
package.json
{
...,
"depencencies": {
"@vue-leaflet/vue-leaflet": "^0.7.0",
"leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3",
},
"devDependencies": {
"nuxt": "^3.0.0",
"typescript": "^4.9.4"
"@types/leaflet.markercluster": "^1.5.1",
}
}
The thing is, now I try to group my markers by adding leaflet.markercluster
. So I added something like this :
leaflet.client.ts
...
import "leaflet.markercluster";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
export default defineNuxtPlugin((nuxtApp) => {
...
return {
provide: {
L,
},
};
});
But now I don't know what to do next. Using L.markerClusterGroup()
as the official documentation says does not work as we get a 500 error for using a client-side method with ssr.
I also tried to directly import in my component with import :
Map.vue
import { MarkerClusterGroup } from 'leaflet.markercluster';
const markersGroup = ref(null);
...
const onLeafletReady = async () => {
markersGroup.value = new MarkerClusterGroup() // NOT WORKING
await nextTick();
leafletObject.value = locationsMap.value;
leafletReady.value = true;
leafletObject.value.addLayer(markersGroup.value)
}
But we got the same problem as using L.anyMethod()
by getting a 500 error.
I saw that Sam85 on this question has the package installed, but that was not the same problem. :/
Has anyone ever tried to make it work with Nuxt 3 ?
Upvotes: 2
Views: 1070
Reputation: 63
I have just been working on integrating leaflet with Nuxt 3.
Since your questions was originally posted a Nuxt 3 specific leaflet module has been released: https://nuxt.com/modules/leaflet
There is a plugin you can install to use leaflet marker clusterer: https://leaflet.nuxtjs.org/guide/marker-cluster.html
The steps I would suggest are:
npx nuxi@latest module add @nuxtjs/leaflet
npm install leaflet.markercluster
export default defineNuxtConfig({
modules: ['@nuxtjs/leaflet'],
leaflet: {
markerCluster: true
}
})
<template>
<div style="height:100vh; width:100vw">
<h1>Marker Cluster</h1>
<LMap
ref="map"
:zoom="6"
:max-zoom="18"
:center="[47.21322, -1.559482]"
:use-global-leaflet="true"
@ready="onMapReady"
>
<LTileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="&copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors"
layer-type="base"
name="OpenStreetMap"
/>
</LMap>
</div>
</template>
<script setup lang="ts">
import L from 'leaflet'
import { ref } from 'vue';
const map = ref(null) as any;
// Create locations data (20 locations around Nantes)
const locations = [
{ name: 'Nantes', lat: 47.218371, lng: -1.553621 },
{ name: 'Saint-Nazaire', lat: 47.273018, lng: -2.213733 },
{ name: 'La Baule', lat: 47.286835, lng: -2.393108 },
];
// When the map is ready
const onMapReady = () => {
useLMarkerCluster({
leafletObject: map.value.leafletObject,
markers: locations
});
}
</script>
await import('leaflet.markercluster')
.I hope this helps :)
Upvotes: 0