Skip to content

Commit 24e1923

Browse files
authored
Add Leaflet.heat support / Rename composables to fit the standards (#41)
- `useLHeat` composable was added to support [Leaflet.heat](https://github.com/Leaflet/Leaflet.heat) - Related tests and documentation were added - `useMarkerCluster` was renamed to `useLMarkerCluster` to fit the [standards](https://nuxt.com/docs/guide/going-further/modules#always-prefix-exposed-interfaces)
1 parent 4e63f57 commit 24e1923

File tree

18 files changed

+355
-21
lines changed

18 files changed

+355
-21
lines changed

docs/.vitepress/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export default defineConfig({
2727
items: [
2828
{ text: 'Using L', link: '/guide/using-l' },
2929
{ text: 'Accessing a map instance', link: '/guide/accessing-map-instance' },
30-
{ text: 'Leaflet.markercluster', link: '/guide/marker-cluster' }
30+
{ text: 'Leaflet.markercluster', link: '/guide/marker-cluster' },
31+
{ text: 'Leaflet.heat', link: '/guide/heat' }
3132
]
3233
},
3334
{

docs/guide/heat.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Using Leaflet.heat
2+
3+
The guide explains how to use the [Leaflet.heat](https://github.com/Leaflet/Leaflet.heat) plugin.
4+
A dedicated composable is available to help you use this plugin.
5+
6+
::: warning
7+
This is only possible in a client-side environment. You should either :
8+
- Use a [Client-Only Page](https://nuxt.com/docs/guide/directory-structure/pages#client-only-pages).
9+
- Wrap your component inside the [ClientOnly](https://nuxt.com/docs/api/components/client-only) component.
10+
- Set your [rendering strategy](https://nuxt.com/docs/guide/concepts/rendering#client-side-rendering) to `ssr: false` for the appropriate route.
11+
:::
12+
13+
## Installation
14+
15+
- First install `leaflet.heat`
16+
17+
```bash
18+
npm install leaflet.heat
19+
```
20+
21+
- Update your Nuxt config to activate the plugin
22+
23+
```ts{3-5}
24+
export default defineNuxtConfig({
25+
modules: ['@nuxtjs/leaflet'],
26+
leaflet: {
27+
heat: true
28+
}
29+
})
30+
```
31+
32+
- Use the `useLHeat` composable in your component
33+
34+
:::warning
35+
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.
36+
:::
37+
38+
```vue{9,23,29-46,50-55}
39+
<template>
40+
<div style="height:100vh; width:100vw">
41+
<h1>Heat</h1>
42+
<LMap
43+
ref="map"
44+
:zoom="17"
45+
:max-zoom="22"
46+
:center="[47.21322, -1.559482]"
47+
:use-global-leaflet="true"
48+
@ready="onMapReady"
49+
>
50+
<LTileLayer
51+
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
52+
attribution="&amp;copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors"
53+
layer-type="base"
54+
name="OpenStreetMap"
55+
/>
56+
</LMap>
57+
</div>
58+
</template>
59+
60+
<script setup lang="ts">
61+
import L from 'leaflet';
62+
import { ref } from 'vue';
63+
64+
const isDrawing = ref(false);
65+
const map = ref(null) as any;
66+
67+
// Create heat data
68+
const heatPoints = [{
69+
lat: 47.21322,
70+
lng: -1.559482,
71+
intensity: 100.0
72+
}, {
73+
lat: 47.21322,
74+
lng: -1.558482,
75+
intensity: 50.0
76+
}, {
77+
lat: 47.21322,
78+
lng: -1.557482,
79+
intensity: 25.0
80+
}, {
81+
lat: 47.21322,
82+
lng: -1.556482,
83+
intensity: 10.0
84+
}];
85+
86+
// When the map is ready
87+
const onMapReady = async () => {
88+
const heat = await useLHeat({
89+
leafletObject: map.value.leafletObject,
90+
heatPoints: heatPoints,
91+
// (optional) radius : default 50
92+
radius: 50,
93+
});
94+
95+
// (optional) Make the heat layer drawable
96+
map.value.leafletObject.on({
97+
movestart: function () { isDrawing.value = false; },
98+
moveend: function () { isDrawing.value = true; },
99+
mousemove: function (e: any) {
100+
if (isDrawing.value) {
101+
heat.addLatLng(e.latlng);
102+
}
103+
}
104+
})
105+
}
106+
</script>
107+
```

docs/guide/marker-cluster.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
# Using Leaflet.markercluster
22

3-
::: warning
4-
This is still not proven as stable because of weird building behavior.
5-
Feel free to report any issue in the Github repository, this could help a lot improving this feature.
6-
:::
7-
83
The guide explains how to use the [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster) plugin.
94
A dedicated composable is available to help you use this plugin.
105

@@ -36,7 +31,7 @@ export default defineNuxtConfig({
3631
})
3732
```
3833

39-
- Use the `useMarkerCluster` composable in your component
34+
- Use the `useLMarkerCluster` composable in your component
4035

4136
:::warning
4237
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.
@@ -107,7 +102,7 @@ const locations = [
107102
108103
// When the map is ready
109104
const onMapReady = () => {
110-
useMarkerCluster({
105+
useLMarkerCluster({
111106
leafletObject: map.value.leafletObject,
112107
markers: locations
113108
});

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@
4848
"@nuxt/schema": "^3.12.4",
4949
"@nuxt/test-utils": "^3.14.0",
5050
"@nuxt/ui": "^2.18.2",
51+
"@types/leaflet.heat": "^0.2.4",
5152
"@types/node": "^20.14.13",
5253
"@typescript-eslint/eslint-plugin": "^7.17.0",
5354
"caniuse-lite": "^1.0.30001643",
5455
"changelogen": "^0.5.5",
5556
"eslint": "^8.57.0",
57+
"leaflet.heat": "^0.2.0",
5658
"leaflet.markercluster": "^1.5.3",
5759
"nuxt": "^3.12.4",
5860
"vitepress": "^1.3.1",

playground/app.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const links = [{
2222
label: 'MarkerCluster',
2323
icon: 'i-heroicons-rectangle-group-16-solid',
2424
to: '/map/markercluster'
25+
}, {
26+
label: 'Heat',
27+
icon: 'i-heroicons-fire-20-solid',
28+
to: '/map/heat'
2529
}, {
2630
label: 'Draw (Deprecated)',
2731
icon: 'i-heroicons-pencil-16-solid',

playground/nuxt.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export default defineNuxtConfig({
1414
},
1515

1616
leaflet: {
17-
markerCluster: true
17+
markerCluster: true,
18+
heat: true
1819
},
1920

2021
compatibilityDate: '2024-07-26'
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<template>
2+
<div style="height:100vh; width:100vw">
3+
<h1>Heat</h1>
4+
<LMap
5+
ref="map"
6+
:zoom="17"
7+
:max-zoom="22"
8+
:center="[47.21322, -1.559482]"
9+
:use-global-leaflet="true"
10+
@ready="onMapReady"
11+
>
12+
<LTileLayer
13+
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
14+
attribution="&amp;copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors"
15+
layer-type="base"
16+
name="OpenStreetMap"
17+
/>
18+
</LMap>
19+
</div>
20+
</template>
21+
22+
<script setup lang="ts">
23+
import L from 'leaflet';
24+
import { ref } from 'vue';
25+
26+
const isDrawing = ref(false);
27+
const map = ref(null) as any;
28+
29+
// Create heat data
30+
const heatPoints = [{
31+
lat: 47.21322,
32+
lng: -1.559482,
33+
intensity: 100.0
34+
}, {
35+
lat: 47.21322,
36+
lng: -1.558482,
37+
intensity: 50.0
38+
}, {
39+
lat: 47.21322,
40+
lng: -1.557482,
41+
intensity: 25.0
42+
}, {
43+
lat: 47.21322,
44+
lng: -1.556482,
45+
intensity: 10.0
46+
}];
47+
48+
// When the map is ready
49+
const onMapReady = async () => {
50+
const heat = await useLHeat({
51+
leafletObject: map.value.leafletObject,
52+
heatPoints: heatPoints,
53+
// (optional) radius : default 50
54+
radius: 50,
55+
});
56+
57+
// (optional) Make the heat layer drawable
58+
map.value.leafletObject.on({
59+
movestart: function () { isDrawing.value = false; },
60+
moveend: function () { isDrawing.value = true; },
61+
mousemove: function (e: any) {
62+
if (isDrawing.value) {
63+
heat.addLatLng(e.latlng);
64+
}
65+
}
66+
})
67+
}
68+
</script>

playground/pages/map/markercluster.client.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const locations = [
6262
6363
// When the map is ready
6464
const onMapReady = () => {
65-
useMarkerCluster({
65+
useLMarkerCluster({
6666
leafletObject: map.value.leafletObject,
6767
markers: locations
6868
});

src/module.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { defineNuxtModule, addComponent, createResolver, addImports } from '@nux
22

33
// Module options TypeScript interface definition
44
export interface ModuleOptions {
5-
markerCluster?: boolean
5+
markerCluster?: boolean,
6+
heat?: boolean
67
}
78

89
// Components to export
@@ -64,11 +65,21 @@ export default defineNuxtModule<ModuleOptions>({
6465
nuxt.options.css.push('leaflet.markercluster/dist/MarkerCluster.css')
6566
nuxt.options.css.push('leaflet.markercluster/dist/MarkerCluster.Default.css')
6667

67-
// Auto-import the runtime composables
68+
// Auto-import the runtime composable
6869
addImports({
69-
name: 'useMarkerCluster',
70-
as: 'useMarkerCluster',
71-
from: resolver.resolve('runtime/composables/useMarkerCluster')
70+
name: 'useLMarkerCluster',
71+
as: 'useLMarkerCluster',
72+
from: resolver.resolve('runtime/composables/useLMarkerCluster')
73+
})
74+
}
75+
76+
// If leaflet.heat is enabled
77+
if (options.heat) {
78+
// Auto-import the runtime composable
79+
addImports({
80+
name: 'useLHeat',
81+
as: 'useLHeat',
82+
from: resolver.resolve('runtime/composables/useLHeat')
7283
})
7384
}
7485
}

0 commit comments

Comments
 (0)