Components

VMap

The core map component for rendering MapLibre GL maps

Usage

<script setup lang="ts">
  import { VMap } from '@geoql/v-maplibre';
  import type { MapOptions } from 'maplibre-gl';

  const mapOptions: MapOptions = {
    style: 'https://demotiles.maplibre.org/style.json',
    center: [-74.5, 40],
    zoom: 9,
  };

  const handleMapLoad = (map) => {
    console.log('Map loaded!', map);
  };
</script>

<template>
  <VMap
    :options="mapOptions"
    @loaded="handleMapLoad"
    style="height: 500px"
  ></VMap>
</template>

Props

options

  • Type: MapOptions
  • Required: true
  • Default: { container: 'map' }

MapLibre GL map options. See MapLibre GL documentation for all available options.

Common options include:

  • style: URL to the map style or a style object
  • center: Initial map center [lng, lat]
  • zoom: Initial zoom level
  • bearing: Initial bearing (rotation)
  • pitch: Initial pitch (tilt)
  • minZoom: Minimum zoom level
  • maxZoom: Maximum zoom level
  • maxBounds: Map bounds constraint

supportPmtiles

  • Type: boolean
  • Required: false
  • Default: false

Enable PMTiles protocol support. Set to true if you plan to use PMTiles layers.

<VMap :options="mapOptions" support-pmtiles></VMap>

Events

@loaded

Emitted when the map has finished loading.

  • Payload: Map - The MapLibre GL Map instance
<VMap @loaded="(map) => console.log('Map ready', map)"></VMap>

Map Events

The VMap component forwards all MapLibre GL map events. You can listen to any map event using the @ directive:

<VMap
  :options="mapOptions"
  @click="handleClick"
  @move="handleMove"
  @zoom="handleZoom"
  @load="handleLoad"
></VMap>

Common events include:

  • @load - Map loaded
  • @click - Map clicked
  • @dblclick - Map double-clicked
  • @move - Map moved
  • @movestart - Map move started
  • @moveend - Map move ended
  • @zoom - Map zoomed
  • @zoomstart - Zoom started
  • @zoomend - Zoom ended

See MapLibre GL Events for the complete list.

Slots

default

The default slot is used to nest child components like markers, popups, layers, and controls.

<VMap :options="mapOptions">
  <VMarker :lng-lat="[0, 0]" />
  <VLayerMaplibreGeojson :source="source" :layer="layer" />
  <VControlNavigation />
</VMap>

Accessing the Map Instance

Child components can access the map instance using Vue's provide/inject API:

<script setup lang="ts">
  import { inject } from 'vue';
  import { MapKey } from '@geoql/v-maplibre/utils/symbols';
  import type { Map } from 'maplibre-gl';
  import type { Ref } from 'vue';

  const map = inject<Ref<Map | null>>(MapKey);

  // Use the map instance
  watch(map, (mapInstance) => {
    if (mapInstance) {
      console.log('Map instance available', mapInstance);
    }
  });
</script>

TypeScript

The component is fully typed with TypeScript. Import types from maplibre-gl:

import type { MapOptions, Map } from 'maplibre-gl';

Examples

Custom Style

<script setup lang="ts">
  import { VMap } from '@geoql/v-maplibre';

  const customStyle = {
    version: 8,
    sources: {
      osm: {
        type: 'raster',
        tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
        tileSize: 256,
        attribution: '© OpenStreetMap Contributors',
      },
    },
    layers: [
      {
        id: 'osm',
        type: 'raster',
        source: 'osm',
      },
    ],
  };

  const mapOptions = {
    style: customStyle,
    center: [0, 0],
    zoom: 2,
  };
</script>

<template>
  <VMap :options="mapOptions" style="height: 100vh"></VMap>
</template>

With Bounds

<script setup lang="ts">
  import { VMap } from '@geoql/v-maplibre';
  import type { LngLatBoundsLike } from 'maplibre-gl';

  const bounds: LngLatBoundsLike = [
    [-74.047285, 40.679548], // Southwest
    [-73.907005, 40.882214], // Northeast
  ];

  const mapOptions = {
    style: 'https://demotiles.maplibre.org/style.json',
    bounds,
    fitBoundsOptions: {
      padding: 20,
    },
  };
</script>

<template>
  <VMap :options="mapOptions" style="height: 500px"></VMap>
</template>