Nuxt Leaflet

repository·main·Indexed 41 days ago

https://github.com/nuxt-modules/leaflet

A Nuxt 3 module that integrates Leaflet maps via Vue components. It leverages Vue Leaflet to provide zero-configuration, auto-imports, and TypeScript support for components such as LMap, LTileLayer, LMarker, and LControlLayers.

Tokens
26.2K
Snippets
63
Records
104
Agent score
50%

What's inside Nuxt Leaflet

  1. How Nuxt Leaflet works

    main

    Nuxt Leaflet is a wrapper around Vue Leaflet, which provides Vue 3 components for the Leaflet API. The module's primary purpose is to integrate these components into Nuxt seamlessly, providing features like:

    • Zero Configuration: Works out of the box without manual nuxt.config setup.
    • Auto-imports: Leaflet components are automatically available in your Nuxt application.
    • TypeScript Support: Full type definitions for a better developer experience.
  2. Use LLayerGroup to group multiple layers

    main

    The LLayerGroup component is used to group several layers and manage them as a single unit. When LLayerGroup is added to the map, any layers added or removed from the group will automatically be added to or removed from the map as well. This is useful for toggling visibility of multiple markers or shapes at once.

    <LMap style="height: 350px" :zoom="8" :center="[47.21322, -1.559482]">
      <LTileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution="&amp;copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors"
        layer-type="base"
        name="OpenStreetMap"
      />
      <LLayerGroup>
        <LMarker :lat-lng="[47.21322, -1.559482]" />
      </LLayerGroup>
    </LMap>
  3. Compare Leaflet with Mapbox and MapLibre

    main

    When choosing a mapping solution for your Nuxt project, consider the following:

    • Leaflet: An open-source technology for creating maps. Use this module for Leaflet integration.
    • Mapbox: A complete collection of advanced mapping tools and services, often requiring paid plans for advanced features. For Nuxt integration, use the nuxt-mapbox module.
    • MapLibre: A free and open-source fork of the original Mapbox GL JS library. For Nuxt integration, use the nuxt-maplibre module.
  4. Access the Leaflet L global variable in Vue components

    main

    If you need to use a Leaflet plugin that is not available as a Vue component, you can import the L global variable directly from the leaflet package.

    To ensure this works correctly, you must enable the global Leaflet instance in your component by setting the :use-global-leaflet="true" prop on the <LMap> component.

    Important: Client-side only Because L relies on browser APIs, this code will fail during Server-Side Rendering (SSR). You must ensure the component is only executed on the client by using one of the following methods:

    • Wrap the component in the <ClientOnly> component.
    • Use a Nuxt Client-Only Page.
    • Set the rendering strategy for the route to ssr: false.
    <template>
      <LMap
        style="height: 350px"
        :zoom="6"
        :center="[47.21322, -1.559482]"
        :use-global-leaflet="true"
      >
        <LTileLayer
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          attribution="&amp;copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors"
          layer-type="base"
          name="OpenStreetMap"
        />
      </LMap>
    </template>
    
    <script setup lang="ts">
    import L from 'leaflet'
    import { onMounted } from 'vue'
    
    // Access L inside onMounted to ensure it runs on the client
    onMounted(() => {
      console.log(L)
    })
    </script>
  5. Install and configure Leaflet.markercluster

    main

    To use marker clustering, you must install the leaflet.markercluster package and enable the plugin in your Nuxt configuration.

    Important: Marker clustering only works in a client-side environment. You must use a Client-Only Page, wrap your component in <ClientOnly>, or set ssr: false for the route.

    Critical Requirement: Because leaflet.markercluster requires Leaflet to be loaded globally, you must manually import Leaflet in your component and set :use-global-leaflet="true" on the <LMap> component.

    npm install leaflet.markercluster
    export default defineNuxtConfig({
      modules: ['@nuxtjs/leaflet'],
      leaflet: {
        markerCluster: true
      }
    })
  6. Use the LPopup component

    main

    The LPopup component is used to display a popup on the map. When placed inside a marker (like LMarker), the popup will appear on marker click by default. You can nest LPopup inside various Leaflet layers such as LMarker, LPolygon, LPolyline, LRectangle, LCircle, or LCircleMarker to associate content with those specific map elements.

    To use it, simply place the <LPopup> component inside the desired layer component and provide the content via the default slot.

    <LMarker :lat-lng="[41.8329, -87.7327]">
      <LPopup> Hi! I'm staying here on this location! </LPopup>
    </LMarker>
  7. Use LGridLayer to render Vue components as map tiles

    main

    The LGridLayer component creates a map layer where every tile is an instantiated Vue component. This is useful for creating custom, interactive, or data-driven tile layers using Vue logic instead of static images.

    To use it, you must provide a childRender function. This function receives a props object containing coords (representing the zoom level z, and position x and y of the tile). The childRender function must return a function that returns a VNode (typically created via Vue's h function).

    Each tile component receives the coords as props, allowing you to render content specific to that tile's position and zoom level.

    <script setup>
    import { h } from 'vue'
    
    // The childRender function receives props containing coords
    const childRender = (props) => () => {
      return h(
        "div",
        { style: "border: 1px solid grey; height: 100%;" },
        `x: ${props.coords.x} y: ${props.coords.y} z: ${props.coords.z}`
      );
    }
    </script>
    
    <template>
      <LMap style="height: 350px" :zoom="8" :center="[47.21322, -1.559482]">
        <LGridLayer :child-render="childRender" />
      </LMap>
    </template>
  8. Display a basic map using LMap and LTileLayer

    main

    To display a map in Nuxt 3, use the LMap component as a container and the LTileLayer component to define the tile provider (e.g., OpenStreetMap).

    Important Implementation Details:

    1. CSS: You must import the Leaflet CSS file: import "leaflet/dist/leaflet.css";.
    2. Leaflet Import: Because Leaflet requires access to the window object, you should dynamically import leaflet inside the onMounted lifecycle hook to ensure it only runs on the client side.
    3. Global Leaflet: If you are already importing Leaflet globally in your application via import L from 'leaflet', you can set the :use-global-leaflet prop to true or omit it.
    <template>
      <LMap
        style="height: 350px"
        :zoom="6"
        :center="[47.21322, -1.559482]"
        :use-global-leaflet="false"
      >
        <LTileLayer
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          attribution="&amp;copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors"
          layer-type="base"
          name="OpenStreetMap"
        />
      </LMap>
    </template>
    
    <script setup>
    import "leaflet/dist/leaflet.css";
    import { LMap, LTileLayer } from "@vue-leaflet/vue-leaflet";
    import { onMounted } from 'vue';
    
    onMounted(() => {
      import('leaflet')
    })
    </script>
  9. Manually install @nuxtjs/leaflet

    main

    If you prefer manual installation, follow these two steps:

    1. Install the package as a dependency using your preferred package manager.
    2. Register the module in your nuxt.config.ts file by adding '@nuxtjs/leaflet' to the modules array.
    npm install @nuxtjs/leaflet
    export default defineNuxtConfig({
      modules: [
        '@nuxtjs/leaflet'
      ]
    })