Skip to content

Composables API Reference ​

Vue3 MapLibre GL provides a comprehensive set of composables for building interactive maps with Vue 3 Composition API. All composables are designed with TypeScript support, reactive data binding, and comprehensive error handling.

Map Composables ​

useCreateMaplibre ​

The core composable for creating and managing MapLibre GL Maps with enhanced error handling and reactive state management.

Parameters ​

ParameterTypeDescription
elRefMaybeRef<HTMLElement | undefined>Reference to the HTML element container
styleRefMaybeRef<StyleSpecification | string>Reference to the map style
propsCreateMaplibrePropsConfiguration options for the map

props also accepts every MapOptions field except container and style, which come from elRef and styleRef.

props fields ​

PropertyTypeDefaultDescription
register(actions) => voidundefinedCallback for registering map actions
debugboolean—Enable debug logging; omitted logs nothing
onLoad(map: Map) => voidundefinedLoad success callback
onError(error: any) => voidundefinedError handling callback

Returns ​

PropertyTypeDescription
mapInstanceComputedRef<Map | null>Reactive map instance
setCenter(center: LngLatLike) => voidSet map center coordinates
setBearing(bearing: number) => voidSet map bearing (rotation)
setZoom(zoom: number) => voidSet map zoom level
setPitch(pitch: number) => voidSet map pitch (tilt)
setStyle(style: StyleSpecification | string) => voidSet map style
setMaxBounds(bounds: LngLatBoundsLike) => voidSet maximum bounds
setMaxPitch(pitch: number) => voidSet maximum pitch
setMaxZoom(zoom: number) => voidSet maximum zoom
setMinPitch(pitch: number) => voidSet minimum pitch
setMinZoom(zoom: number) => voidSet minimum zoom
setRenderWorldCopies(render: boolean) => voidSet world copies rendering
mapCreationStatusComputedRef<MapCreationStatus>Current creation status
isMapReadyComputedRef<boolean>Whether the map is ready
isMapLoadingComputedRef<boolean>Whether the map is loading
hasMapErrorComputedRef<boolean>Whether the map has an error
getCurrentCamera() => CameraOptions | nullRead the camera as it is now
getCurrentStyle() => StyleSpecification | string | nullRead the active style
initMap() => voidCreate the map
removeMap() => voidRemove the map from the DOM
destroyMap() => voidDestroy the map instance

initMap runs on its own once the container and style are available; call it only if you removed the map yourself. Everything except the three lifecycle methods is also handed to register.

Example ​

typescript
import { ref } from 'vue';
import { useCreateMaplibre } from 'vue3-maplibre-gl';

const mapContainer = ref<HTMLElement>();
const mapStyle = ref('https://demotiles.maplibre.org/style.json');

const { mapInstance, setCenter, setZoom, isMapReady, isMapLoading } =
  useCreateMaplibre(mapContainer, mapStyle, {
    debug: true,
    onLoad: (map) => {
      console.log('Map loaded:', map);
    },
    onError: (error) => {
      console.error('Map error:', error);
    },
  });

// Use the map instance
watch(isMapReady, (ready) => {
  if (ready) {
    setCenter([0, 0]);
    setZoom(10);
  }
});

useMaplibre ​

Holds a map created elsewhere, so a component that renders <Maplibre> can drive it without reaching into a template ref. It creates no map of its own: hand it the actions <Maplibre> emits, via @register.

Parameters ​

ParameterTypeDefaultDescription
optionsobject{}Configuration options
options.debugbooleanfalseLog registration and map operations
options.autoCleanupbooleantrueRelease the registered instance on unmount

Returns ​

PropertyTypeDescription
mapInstanceComputedRef<Map | null>Reactive map instance
mapStatusComputedRef<MapCreationStatus>Current creation status
isMapReadyComputedRef<boolean>Whether the map is ready for operations
isMapLoadingComputedRef<boolean>Whether the map is currently loading
hasMapErrorComputedRef<boolean>Whether map creation failed
isRegisteredComputedRef<boolean>Whether an instance has been registered
register(instance: MaplibreActions) => Promise<void>Register an actions instance
setMapOptions(options: Partial<MapOptions>) => voidOverride individual options on the registered instance. Only the keys passed here are overridden; every other key keeps tracking the :options prop.

It also spreads in every accessor and setter of MaplibreMethods — getCenter, getZoom, queryRenderedFeatures, setStyle, flyTo and the rest — each of which no-ops while no map is registered.

The status field is mapStatus, not mapCreationStatus, and there are no lifecycle methods: initMap, removeMap and destroyMap belong to useCreateMaplibre, which owns the map.

Example ​

vue
<script setup>
import { ref, watch } from 'vue';
import { Maplibre, useMaplibre } from 'vue3-maplibre-gl';

const options = ref({
  style: 'https://demotiles.maplibre.org/style.json',
  center: [0, 0],
  zoom: 2,
});

const {
  register: registerMap,
  mapInstance,
  isMapReady,
} = useMaplibre({ debug: true });

// Every field is a ComputedRef — read it with .value in script, unwrapped in template
watch(isMapReady, (ready) => {
  if (ready) console.log(mapInstance.value?.getZoom());
});
</script>

<template>
  <Maplibre :options="options" @register="registerMap" />
</template>

Before register runs, mapInstance is null and every method is a no-op — isMapReady is the signal that the map is usable.

To reach the map from a component nested inside <Maplibre>, inject MapProvideKey instead; that is what the built-in child components do.

useMaplibreConfig ​

Configures MapLibre GL's global performance settings (web worker count, parallel image requests, resource prewarming). Call it once at app startup (e.g. in App.vue or main.ts) — it applies to every map instance in your app, not just one map.

Signature ​

typescript
function useMaplibreConfig(
  options?: MaplibreConfigOptions,
): MaplibreConfigActions;

Parameters (MaplibreConfigOptions) ​

PropertyTypeDefaultDescription
workerCountnumber4Number of web workers for tile loading
maxParallelImageRequestsnumber16Maximum parallel image requests
prewarmResourcesbooleantruePrewarm MapLibre resources on initialization
debugbooleanfalseEnable debug logging

Returns ​

PropertyTypeDescription
clearPrewarmedResources() => voidReleases prewarmed resources (called automatically on unmount)

Example ​

vue
<script setup>
import { useMaplibreConfig } from 'vue3-maplibre-gl';

// Call once, at the top of your root component
useMaplibreConfig({
  workerCount: 4,
  maxParallelImageRequests: 16,
  prewarmResources: true,
});
</script>

useCreateImage ​

Adds a custom image (icon) to the map's style so it can be used by symbol layers, e.g. 'icon-image': 'my-icon'. Handles loading images from a URL, updating them, and safely re-adding them when their size changes (MapLibre requires images to keep the same dimensions when updated).

Signature ​

typescript
function useCreateImage(props: CreateImageProps): CreateImageActions;

Parameters (CreateImageProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
idstring—Image identifier used in layer styles
imageImageDatas | string—Image data (HTMLImageElement, ImageBitmap, ImageData, or raw pixel object) or a URL string to load
optionsPartial<StyleImageMetadata>—Image metadata (e.g. pixelRatio, sdf)
forceRecreateOnDimensionChangeboolean—Remove+re-add on dimension change instead of trying an in-place update; omitted is read as true
debugboolean—Enable debug logging

Returns ​

PropertyTypeDescription
remove() => voidRemove the image from the map
loadImage(imageUrl: string) => Promise<HTMLImageElement | ImageBitmap>Load an image from a URL
updateImage(newImage: ImageDatas | string) => Promise<void>Replace the current image
refreshImage() => Promise<void>Re-apply the current image
hasImage() => booleanWhether the image currently exists on the map
imageStatusComputedRef<ImageStatus>'not-created' | 'loading' | 'created' | 'updated' | 'error'
isImageReadyComputedRef<boolean>Whether the image is created or updated
loadPromisePromise<void>Resolves once the image is first added, rejects if removed or on error

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useCreateImage } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

useCreateImage({
  map: mapInstance,
  id: 'my-icon',
  image: '/icons/pin.png',
});
// Now usable in a symbol layer: 'icon-image': 'my-icon'
</script>

useCreateMarker ​

Wraps MapLibre GL's Marker class so a DOM pin/icon can be placed on the map and moved reactively, with drag events and automatic cleanup on unmount.

Signature ​

typescript
function useCreateMarker(props: CreateMarkerProps): CreateMarkerActions;

Parameters (CreateMarkerProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
lnglatMaybeRef<LngLatLike | undefined>—Marker position, reactive
popupMaybeRef<Popup | null>—Popup to attach to the marker
elRef<HTMLElement | undefined>—Custom DOM element to use as the marker (from a template ref)
optionsMarkerOptions{}Native MapLibre Marker options
on{ dragstart?, drag?, dragend? }{}Drag event handlers
autoAddbooleantrueAutomatically add the marker to the map
debugbooleanfalseEnable debug logging

Returns ​

PropertyTypeDescription
markerComputedRef<Marker | null>The underlying MapLibre Marker instance
markerStatusComputedRef<MarkerStatus>'not-created' | 'creating' | 'created' | 'error'
isMarkerCreatedComputedRef<boolean>Whether the marker has been created
setLngLat(lnglat: LngLatLike) => voidMove the marker
setPopup(popup?: Popup | null) => voidAttach/detach a popup
setOffset(offset: PointLike) => voidSet pixel offset
setDraggable(draggable: boolean) => voidToggle draggable state
togglePopup() => voidOpen/close the attached popup
getElement() => HTMLElement | nullGet the marker's DOM element
setRotation(rotation: number) => voidSet rotation in degrees
setRotationAlignment(alignment: Alignment) => voidSet rotation alignment
setPitchAlignment(alignment: Alignment) => voidSet pitch alignment
setOpacity(opacity: string, opacityWhenCovered?: string) => voidSet opacity
removeMarker() => voidRemove the marker from the map
addMarker() => voidAdd the marker back to the map
getLngLat() => LngLatLike | nullCurrent position
getPopup() => Popup | nullCurrently attached popup
getOffset() => PointLikeCurrent pixel offset
getDraggable() => booleanWhether the marker is draggable
getRotation() => numberCurrent rotation

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useCreateMarker } from 'vue3-maplibre-gl';

const mapInstance = ref(null);
const position = ref([0, 0]);

const { setLngLat, setDraggable } = useCreateMarker({
  map: mapInstance,
  lnglat: position,
  options: { color: '#FF0000' },
  on: {
    dragend: () => console.log('Marker dropped'),
  },
});

setDraggable(true);
</script>

useCreatePopup ​

Wraps MapLibre GL's Popup class to show HTML content or a custom DOM element at a given map location, with reactive content and position.

Signature ​

typescript
function useCreatePopup(props: CreatePopupProps): CreatePopupActions;

Parameters (CreatePopupProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
lnglatMaybeRef<LngLatLike | undefined>—Popup position, reactive
htmlMaybeRef<string | undefined>—Popup HTML content, reactive
elRef<HTMLElement | undefined>—Custom DOM element to use as content
optionsPopupOptions{}Native MapLibre Popup options
showbooleantrueShow the popup immediately once created
withMapbooleantrueAttach the popup to the map
autoCreatebooleantrueAuto-create the popup when the map becomes available
closeOnClickbooleantrueClose popup when the map is clicked
closeButtonbooleantrueShow the close (×) button
on{ open?, close? }{}Open/close event handlers
debugbooleanfalseEnable debug logging

Returns ​

PropertyTypeDescription
popupComputedRef<Popup | null>The underlying MapLibre Popup instance
popupStatusComputedRef<PopupStatus>'not-created' | 'creating' | 'created' | 'open' | 'closed' | 'error'
isPopupCreatedComputedRef<boolean>Whether the popup has been created
isPopupOpenComputedRef<boolean>Whether the popup is currently open
setLngLat(lnglat: LngLatLike) => voidMove the popup
setOffset(offset: PointLike) => voidSet pixel offset
addClassName(className: string) => voidAdd a CSS class to the popup
removeClassName(className: string) => voidRemove a CSS class
setMaxWidth(width: string) => voidSet max width (CSS value)
show() => voidShow the popup on the map
hide() => voidHide the popup from the map
toggle() => voidToggle visibility
addToMap() => voidAdd popup to map without opening it
setHTMLContent(html?: string) => voidUpdate HTML content
setDOMContent(element: HTMLElement) => voidUpdate DOM content
setText(text: string) => voidUpdate text content (escaped)
removePopup() => voidRemove and clean up the popup
createPopup() => voidManually (re)create the popup
getLngLat() => LngLatLike | nullCurrent position
getElement() => HTMLElement | nullPopup's DOM element

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useCreatePopup } from 'vue3-maplibre-gl';

const mapInstance = ref(null);
const position = ref([0, 0]);

const { show, hide, setHTMLContent } = useCreatePopup({
  map: mapInstance,
  lnglat: position,
  html: '<strong>Hello!</strong>',
  show: false,
});

show();
</script>

useLayer ​

Registers a layer instance (e.g. from useCreateFillLayer) and re-exposes its actions plus richer reactive status tracking. Useful when a component needs to manage a layer created elsewhere via the register callback pattern.

Signature ​

typescript
function useLayer<T extends LayerSpecification>(
  props?: LayerManagementProps,
): LayerManagementActions;

Parameters (LayerManagementProps) ​

PropertyTypeDefaultDescription
debugbooleanfalseEnable debug logging
autoCleanupbooleantrueDispose automatically on unmount

Returns ​

PropertyTypeDescription
register(instance: CreateLayerActions<any>, map: Map) => voidRegister a layer instance (pass this as the register callback of a useCreate*Layer composable)
layerIdComputedRef<string | undefined>Registered layer's ID
layerComputedRef<LayerSpecification | null>Registered layer specification
layerStatusComputedRef<LayerManagementStatus>'not-registered' | 'registering' | 'registered' | 'error' | 'disposed'
isLayerRegisteredComputedRef<boolean>Whether a layer instance is registered
isLayerReadyComputedRef<boolean>Whether the layer exists on the map now
getFilter() => FilterSpecification | voidCurrent filter
getLayoutProperty(name: keyof AnyLayout) => anyGet a layout property
getPaintProperty(name: keyof AnyPaint) => anyGet a paint property
setBeforeId(beforeId?: string) => voidReposition the layer
setFilter(filter?: FilterSpecification) => voidUpdate filter
setPaintProperty(name: string, value: any, options?: StyleSetterOptions) => voidUpdate paint property
setLayoutProperty(name: string, value: any, options?: StyleSetterOptions) => voidUpdate layout property
setZoomRange(minzoom?: number, maxzoom?: number) => voidUpdate zoom range
removeLayer() => voidRemove the layer
setStyle(style: AnyLayout & AnyPaint) => voidUpdate layer style
dispose() => voidStop tracking and release resources
refresh() => voidRe-register the current instance

Example ​

vue
<script setup>
import { useCreateFillLayer, useLayer } from 'vue3-maplibre-gl';

const { register: registerLayerActions, isLayerReady, setStyle } = useLayer();

useCreateFillLayer({
  map: mapInstance,
  source: sourceRef,
  id: 'fill-layer',
  style: { 'fill-color': '#088' },
  register: registerLayerActions,
});
</script>

Layer Composables ​

useCreateLayer ​

The generic, low-level layer composable that useCreateFillLayer, useCreateCircleLayer, useCreateLineLayer, and useCreateSymbolLayer are all built on top of. Use it directly when you need a layer type not covered by the specific helpers, or full control over paint/layout.

Signature ​

typescript
function useCreateLayer<Layer extends LayerSpecification>(
  cfg: CreateBaseLayerProps<Layer>,
): EnhancedLayerActions<Layer>;

Parameters (CreateBaseLayerProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
sourceMaybeRef<string | SourceSpecification | object | null | undefined>—Source id, spec, or reactive reference
typeLayerTypes—MapLibre layer type (e.g. 'fill', 'line')
idstring—Layer id (auto-generated if omitted)
beforeIdstring—Insert layer before this layer id
filterFilterSpecification['all']Filter expression
layoutLayer['layout']{}Layout properties
paintLayer['paint']{}Paint properties
maxzoomnumber24Maximum zoom
minzoomnumber0Minimum zoom
metadataobject—Layer metadata
sourceLayerstring''Vector tile source layer name
debugbooleanfalseEnable debug logging
register(actions: CreateBaseLayerActions<Layer>, map: Map) => void—Registration callback

Returns ​

PropertyTypeDescription
layerIdstringGenerated/provided layer id
getLayerComputedRef<LayerSpecification | null>Current layer specification
removeLayer() => voidRemove the layer
setBeforeId(beforeId?: string) => voidReposition the layer
setFilter(filter?: FilterSpecification) => voidUpdate filter
setZoomRange(minzoom?: number, maxzoom?: number) => voidUpdate zoom range
setPaintProperty(name: string, value: any, options?: StyleSetterOptions) => voidUpdate a paint property
setLayoutProperty(name: string, value: any, options?: StyleSetterOptions) => voidUpdate a layout property
layerStatusComputedRef<LayerStatus>'not-created' | 'creating' | 'created' | 'error'
isLayerReadyComputedRef<boolean>Whether the layer currently exists on the map
refreshLayer() => voidRemove and recreate the layer
updateLayer(updates: { filter?, minzoom?, maxzoom?, paint?, layout? }) => voidApply several updates in one call

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useCreateLayer } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

const { getLayer, updateLayer } = useCreateLayer({
  map: mapInstance,
  source: 'my-source',
  type: 'heatmap',
  id: 'heatmap-layer',
  paint: { 'heatmap-weight': 1 },
});

updateLayer({ paint: { 'heatmap-weight': 2 } });
</script>

useCreateFillLayer ​

Creates and manages MapLibre GL Fill Layers with reactive updates and comprehensive event handling.

Parameters ​

PropertyTypeDescription
mapMaybeRef<Map | null>Map instance reference
sourceMaybeRef<string | SourceSpecification | object>Source id, or a spec with an id
styleFillLayerStyleFill layer style configuration
filterFilterSpecificationFilter expression
idstringLayer identifier
beforeIdstringInsert before this layer
maxzoomnumberMaximum zoom level
minzoomnumberMinimum zoom level
metadataobjectLayer metadata
sourceLayerstringSource layer name
debugbooleanEnable debug logging
register(actions: CreateLayerActions<FillLayerSpecification>, map: Map) => voidRegistration callback

A layer references its source by id, so an object passed to source must carry its own string id; a bare { type: 'geojson', data } is rejected with an error rather than reaching addLayer.

Returns ​

PropertyTypeDescription
layerIdstringThe layer's resolved id
getLayerComputedRef<FillLayerSpecification | null>Get layer specification
setStyle(style?: FillLayerStyle) => voidSet layer style
setBeforeId(beforeId?: string) => voidSet layer insertion point
setFilter(filter?: FilterSpecification) => voidSet layer filter
setZoomRange(minzoom?: number, maxzoom?: number) => voidSet zoom range
setPaintProperty(name, value, options?) => voidSet one paint property
setLayoutProperty(name, value, options?) => voidSet one layout property
removeLayer() => voidRemove the layer
setColor(color: string) => voidSet fill-color
setOpacity(opacity: number) => voidSet fill-opacity
setOutlineColor(color: string) => voidSet fill-outline-color
setPattern(pattern: string) => voidSet fill-pattern
setAntialias(antialias: boolean) => voidSet fill-antialias
setSortKey(sortKey: number) => voidSet fill-sort-key
setVisibility(visibility: 'visible' | 'none') => voidShow or hide the layer

Every set* above other than setStyle also takes an optional StyleSetterOptions as its last argument.

Example ​

typescript
import { ref } from 'vue';
import { useCreateFillLayer } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);
const sourceRef = ref('my-source');

const { getLayer, setStyle, setFilter } = useCreateFillLayer({
  map: mapInstance,
  source: sourceRef,
  id: 'fill-layer',
  style: {
    'fill-color': '#088',
    'fill-opacity': 0.8,
  },
  filter: ['==', 'type', 'polygon'],
  register: (actions, map) => {
    console.log('Fill layer registered:', actions);
  },
});

// Update layer style
setStyle({
  'fill-color': '#ff0000',
  'fill-opacity': 0.6,
});

// Update layer filter
setFilter(['==', 'category', 'important']);

useCreateCircleLayer ​

Creates and manages MapLibre GL Circle Layers for point data visualization.

Parameters ​

The same props as useCreateFillLayer, with CircleLayerStyle for style.

Returns ​

PropertyTypeDescription
layerIdstringThe layer's resolved id
getLayerComputedRef<CircleLayerSpecification | null>Get layer specification
setStyle(style?: CircleLayerStyle) => voidSet layer style
setBeforeId(beforeId?: string) => voidSet layer insertion point
setFilter(filter?: FilterSpecification) => voidSet layer filter
setZoomRange(minzoom?: number, maxzoom?: number) => voidSet zoom range
setPaintProperty(name, value, options?) => voidSet one paint property
setLayoutProperty(name, value, options?) => voidSet one layout property
removeLayer() => voidRemove the layer
setRadius(radius: number | string) => voidSet circle-radius
setColor(color: string) => voidSet circle-color
setOpacity(opacity: number) => voidSet circle-opacity
setStrokeWidth(width: number) => voidSet circle-stroke-width
setStrokeColor(color: string) => voidSet circle-stroke-color
setStrokeOpacity(opacity: number) => voidSet circle-stroke-opacity
setVisibility(visibility: 'visible' | 'none') => voidShow or hide the layer

Every set* above other than setStyle also takes an optional StyleSetterOptions as its last argument.

Example ​

typescript
import { useCreateCircleLayer } from 'vue3-maplibre-gl';

const { getLayer, setStyle } = useCreateCircleLayer({
  map: mapInstance,
  source: sourceRef,
  id: 'circle-layer',
  style: {
    'circle-radius': 6,
    'circle-color': '#007cbf',
    'circle-stroke-width': 2,
    'circle-stroke-color': '#fff',
  },
});

useCreateLineLayer ​

Creates and manages MapLibre GL Line Layers for linear features.

Parameters ​

The same props as useCreateFillLayer, with LineLayerStyle for style.

Returns ​

PropertyTypeDescription
layerIdstringThe layer's resolved id
getLayerComputedRef<LineLayerSpecification | null>Get layer specification
setStyle(style?: LineLayerStyle) => voidSet layer style
setBeforeId(beforeId?: string) => voidSet layer insertion point
setFilter(filter?: FilterSpecification) => voidSet layer filter
setZoomRange(minzoom?: number, maxzoom?: number) => voidSet zoom range
setPaintProperty(name, value, options?) => voidSet one paint property
setLayoutProperty(name, value, options?) => voidSet one layout property
removeLayer() => voidRemove the layer
setColor(color: string) => voidSet line-color
setWidth(width: number | string) => voidSet line-width
setOpacity(opacity: number) => voidSet line-opacity
setBlur(blur: number) => voidSet line-blur
setCap(cap: 'butt' | 'round' | 'square') => voidSet line-cap
setJoin(join: 'bevel' | 'round' | 'miter') => voidSet line-join
setOffset(offset: number) => voidSet line-offset
setGapWidth(gapWidth: number) => voidSet line-gap-width
setDashArray(dashArray: number[]) => voidSet line-dasharray
setGradient(gradient: string) => voidSet line-gradient
setPattern(pattern: string) => voidSet line-pattern
setSortKey(sortKey: number) => voidSet line-sort-key
setVisibility(visibility: 'visible' | 'none') => voidShow or hide the layer

Every set* above other than setStyle also takes an optional StyleSetterOptions as its last argument.

Example ​

typescript
import { useCreateLineLayer } from 'vue3-maplibre-gl';

const { getLayer, setStyle } = useCreateLineLayer({
  map: mapInstance,
  source: sourceRef,
  id: 'line-layer',
  style: {
    'line-color': '#007cbf',
    'line-width': 3,
    'line-opacity': 0.8,
  },
});

useCreateSymbolLayer ​

Creates and manages MapLibre GL Symbol Layers for icons and text.

Parameters ​

The same props as useCreateFillLayer, with SymbolLayerStyle for style.

Returns ​

PropertyTypeDescription
layerIdstringThe layer's resolved id
getLayerComputedRef<SymbolLayerSpecification | null>Get layer specification
setStyle(style?: SymbolLayerStyle) => voidSet layer style
setBeforeId(beforeId?: string) => voidSet layer insertion point
setFilter(filter?: FilterSpecification) => voidSet layer filter
setZoomRange(minzoom?: number, maxzoom?: number) => voidSet zoom range
setPaintProperty(name, value, options?) => voidSet one paint property
setLayoutProperty(name, value, options?) => voidSet one layout property
removeLayer() => voidRemove the layer
setIconImage(image: string) => voidSet icon-image
setIconSize(size: number | string) => voidSet icon-size
setIconColor(color: string) => voidSet icon-color
setIconOpacity(opacity: number) => voidSet icon-opacity
setIconRotate(rotation: number) => voidSet icon-rotate
setIconOffset(offset: [number, number]) => voidSet icon-offset
setIconAnchor(anchor: string) => voidSet icon-anchor
setIconHaloColor(color: string) => voidSet icon-halo-color
setIconHaloWidth(width: number) => voidSet icon-halo-width
setIconHaloBlur(blur: number) => voidSet icon-halo-blur
setTextField(field: string) => voidSet text-field
setTextFont(font: string[]) => voidSet text-font
setTextSize(size: number | string) => voidSet text-size
setTextColor(color: string) => voidSet text-color
setTextOpacity(opacity: number) => voidSet text-opacity
setTextRotate(rotation: number) => voidSet text-rotate
setTextOffset(offset: [number, number]) => voidSet text-offset
setTextAnchor(anchor: string) => voidSet text-anchor
setTextHaloColor(color: string) => voidSet text-halo-color
setTextHaloWidth(width: number) => voidSet text-halo-width
setTextHaloBlur(blur: number) => voidSet text-halo-blur
setSortKey(sortKey: number) => voidSet symbol-sort-key
setVisibility(visibility: 'visible' | 'none') => voidShow or hide the layer

Every set* above other than setStyle also takes an optional StyleSetterOptions as its last argument.

Example ​

typescript
import { useCreateSymbolLayer } from 'vue3-maplibre-gl';

const { getLayer, setStyle } = useCreateSymbolLayer({
  map: mapInstance,
  source: sourceRef,
  id: 'symbol-layer',
  style: {
    'text-field': ['get', 'name'],
    'text-font': ['Open Sans Regular'],
    'text-size': 12,
    'text-color': '#333',
  },
});

Source Composables ​

useCreateGeoJsonSource ​

Creates and manages MapLibre GL GeoJSON Sources with reactive data updates and comprehensive error handling.

Parameters ​

ParameterTypeDescription
propsCreateGeoJsonSourcePropsGeoJSON source configuration

CreateGeoJsonSourceProps Interface ​

PropertyTypeDescription
mapMaybeRef<Map | null>Map instance reference
idstringSource identifier
dataGeoJSONSourceSpecification['data']GeoJSON data
optionsPartial<GeoJSONSourceSpecification>Additional source options
debugbooleanEnable debug logging
register(actions: CreateGeoJsonSourceActions, map: Map) => voidRegistration callback

Returns ​

PropertyTypeDescription
sourceIdstringSource identifier
getSourceShallowRef<GeoJSONSource | null>Get source instance
setData(data: GeoJSONSourceSpecification['data']) => voidUpdate source data
removeSource() => voidRemove source from map
refreshSource() => voidRefresh source
sourceStatusComputedRef<SourceStatus>Source status
isSourceReadyComputedRef<boolean>Whether source is ready

Example ​

typescript
import { ref } from 'vue';
import { useCreateGeoJsonSource } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);
const geoJsonData = ref({
  type: 'FeatureCollection',
  features: [],
});

const { sourceId, getSource, setData, isSourceReady } = useCreateGeoJsonSource({
  map: mapInstance,
  id: 'my-geojson-source',
  data: geoJsonData.value,
  options: {
    cluster: true,
    clusterMaxZoom: 14,
    clusterRadius: 50,
  },
  debug: true,
  register: (actions, map) => {
    console.log('GeoJSON source registered:', actions);
  },
});

// Update source data
const newData = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [0, 0],
      },
      properties: {
        name: 'Sample Point',
      },
    },
  ],
};

setData(newData);

useGeoJsonSource ​

A simplified composable for managing GeoJSON source instances with enhanced error handling.

Parameters ​

ParameterTypeDescription
propsUseGeoJsonSourcePropsConfiguration options

Returns ​

PropertyTypeDescription
sourceIdComputedRef<string | undefined>Source identifier
getSourceComputedRef<GeoJSONSource | null>Get source instance
setData(data: GeoJSONSourceSpecification['data']) => voidUpdate source data
refreshSource() => voidRefresh source
isSourceReadyComputedRef<boolean>Whether source is ready
sourceStatusComputedRef<GeoJsonSourceStatus>Source status
register(instance: CreateGeoJsonSourceActions) => voidBind a source created by <GeoJsonSource>

Example ​

typescript
import { useGeoJsonSource } from 'vue3-maplibre-gl';

const { sourceId, getSource, setData, isSourceReady, register } =
  useGeoJsonSource({
    debug: true,
    autoRefresh: true,
  });

// Register with a source instance
register(sourceActions);

Control Composables ​

useGeolocateControl ​

Creates and manages MapLibre GL Geolocate Controls with comprehensive event handling.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
positionControlPosition'bottom-right'Control position on map
optionsGeolocateControlOptions{}Control options
debugbooleanfalseEnable debug logging

Returns ​

PropertyTypeDescription
geolocateControlShallowRef<GeolocateControl | null>Control instance
isControlAddedShallowRef<boolean>Whether the control is on the map
addControl() => voidAdd the control to the map
removeControl() => voidRemove the control from the map
trigger() => voidTrigger geolocation

Example ​

typescript
import { ref } from 'vue';
import { useGeolocateControl } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);

const { geolocateControl, isControlAdded, trigger } = useGeolocateControl({
  map: mapInstance,
  position: 'top-right',
  options: {
    positionOptions: {
      enableHighAccuracy: true,
    },
    trackUserLocation: true,
  },
  debug: true,
});

// The control adds itself once the map exists; trigger no-ops before then.
watch(isControlAdded, (added) => {
  if (added) trigger();
});

Event Composables ​

useMapEventListener ​

Provides reactive event handling for MapLibre GL map events with automatic cleanup.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
eventkeyof MapEventTypes—Event type to listen for
on(event) => void—Event handler
oncebooleanundefinedDetach after the first event; anything falsy, omission included, keeps listening
debugbooleanundefinedEnable debug logging; omitted logs nothing

The handler prop is on, not handler.

Returns ​

PropertyTypeDescription
attachListener() => voidAttach the listener manually
removeListener() => voidDetach the listener (idempotent)
isListenerAttachedComputedRef<boolean>Whether the listener is attached
listenerStatusComputedRef<EventListenerStatus>Current listener status

The listener attaches itself once the map exists and detaches on unmount, so most callers never touch these.

Example ​

typescript
import { ref } from 'vue';
import { useMapEventListener } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);

// Listen for map click events
useMapEventListener({
  map: mapInstance,
  event: 'click',
  on: (event) => {
    console.log('Map clicked at:', event.lngLat);
  },
});

// Listen for map zoom events
useMapEventListener({
  map: mapInstance,
  event: 'zoom',
  on: (event) => {
    console.log('Map zoom level:', event.target.getZoom());
  },
});

useLayerEventListener ​

Provides reactive event handling for MapLibre GL layer events with automatic cleanup.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
layerMaybeRef<LayerSpecification | string | null>—Layer, or its id
eventkeyof MapLayerEventType—Event type to listen for
on(event) => void—Event handler
oncebooleanundefinedDetach after the first event; anything falsy, omission included, keeps listening
debugbooleanundefinedEnable debug logging; omitted logs nothing

The layer prop is layer and accepts a specification as well as an id; the handler prop is on, not handler.

Returns ​

Everything useMapEventListener returns, plus:

PropertyTypeDescription
layerIdComputedRef<string | null>The resolved id of the watched layer

Example ​

typescript
import { ref } from 'vue';
import { useLayerEventListener } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);

// Listen for layer click events
useLayerEventListener({
  map: mapInstance,
  layer: 'my-layer',
  event: 'click',
  on: (event) => {
    console.log('Layer clicked:', event.features[0]);
  },
});

// Listen for layer hover events
useLayerEventListener({
  map: mapInstance,
  layer: 'my-layer',
  event: 'mouseenter',
  on: (event) => {
    console.log('Mouse entered layer:', event.features[0]);
  },
});

useGeolocateEventListener ​

Listens to events from a GeolocateControl instance (e.g. geolocate, trackuserlocationstart, error), the geolocate-specific counterpart to useMapEventListener.

Signature ​

typescript
function useGeolocateEventListener<T extends keyof GeolocateEventTypes>(
  props: GeolocateEventListenerProps<T>,
): EventListenerActions;

Parameters ​

PropertyTypeDescription
geolocateMaybeRef<GeolocateControl | null>Geolocate control instance (from useGeolocateControl)
eventkeyof GeolocateEventTypesEvent name, e.g. 'geolocate', 'error'
on(event: GeolocateEventTypes[T]) => voidEvent handler, typed by event
oncebooleanListen only once
debugbooleanEnable debug logging

Returns ​

PropertyTypeDescription
attachListener() => voidAttach the handler if it is detached
removeListener() => voidDetach the handler
isListenerAttachedComputedRef<boolean>Whether the handler is attached
listenerStatusComputedRef<EventListenerStatus>Current listener status

The same EventListenerActions shape as useMapEventListener and useLayerEventListener.

Example ​

vue
<script setup>
import {
  useGeolocateControl,
  useGeolocateEventListener,
} from 'vue3-maplibre-gl';

const { geolocateControl } = useGeolocateControl({ map: mapInstance });

useGeolocateEventListener({
  geolocate: geolocateControl,
  event: 'geolocate',
  on: (position) => {
    console.log('User located at:', position.coords);
  },
});
</script>

useMapReloadEvent ​

Low-level building block that tracks the map's load/styledata/styledataloading events and fires onLoad/onUnload callbacks whenever the style is (re)loaded — including on style switches, not just the initial load. Many other composables (like useCreateLayer) use this internally to recreate their layers/sources after a style change.

Signature ​

typescript
function useMapReloadEvent(props: MapReloadEventProps): MapReloadEventActions;

Parameters (MapReloadEventProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
callbacks.onLoad(map: Map) => void—Called when the style finishes (re)loading
callbacks.onUnload(map: Map) => void—Called when the style starts reloading (optional)
callbacks.onError(error: any) => void—Called on handler errors (optional)
debugboolean—Enable debug logging
autoTriggerOnMountboolean—Fire onLoad immediately if the style is already loaded; only an explicit false disables it

Returns ​

PropertyTypeDescription
clear() => voidRemove all listeners
forceLoad() => voidManually trigger the load callback
forceUnload() => voidManually trigger the unload callback
isMapLoadedComputedRef<boolean>Whether the style is currently loaded
loadStatusComputedRef<MapReloadEventStatus>'not-loaded' | 'loading' | 'loaded' | 'error'

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useMapReloadEvent } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

useMapReloadEvent({
  map: mapInstance,
  callbacks: {
    onLoad: (map) => console.log('Style (re)loaded'),
    onUnload: (map) => console.log('Style is being replaced'),
  },
});
</script>

Camera Composables ​

Composables for moving the map's camera (panning, rotating, zooming, and fitting to bounds). All of them return a promise-based action plus a status enum you can watch ('not-started' | '...ing' | 'completed' | 'error'), and all accept either a props object (recommended) or the legacy (map, options) call signature for backward compatibility. They all clean up in-flight animations automatically on unmount.

usePanBy / usePanTo ​

Pans the map by a pixel offset (usePanBy) or to a specific coordinate (usePanTo), with animation.

Signature ​

typescript
function usePanBy(props: PanByProps): PanByActions;
function usePanTo(props: PanToProps): PanToActions;

Parameters ​

The two take the same props but for the target: usePanBy moves by a pixel offset, usePanTo to a coordinate.

usePanBy

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
offsetPointLike—Pixel offset [x, y]
optionsAnimationOptions—Animation options (duration, easing, etc.)
autoPanboolean—Auto-pan once offset and map are set; only an explicit false disables it
debugboolean—Enable debug logging

usePanTo

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
lnglatLngLatLike—Target coordinate
optionsAnimationOptions—Animation options (duration, easing, etc.)
autoPanboolean—Auto-pan once lnglat and map are set; only an explicit false disables it
debugboolean—Enable debug logging

Returns ​

Both return the same four fields:

PropertyTypeDescription
stopPanning() => voidStops the in-progress pan
getCurrentCamera() => CameraOptions | nullCurrent { center, zoom, bearing, pitch }
panStatusComputedRef<PanStatus>'not-started' | 'panning' | 'completed' | 'error'
isPanningComputedRef<boolean>Whether a pan is in progress

usePanBy

PropertyTypeDescription
panBy(offset: PointLike, options?: AnimationOptions) => Promise<void>Executes the pan, resolves on moveend
validatePanOffset(offset: PointLike) => booleanValidates the offset shape

usePanTo

PropertyTypeDescription
panTo(lnglat: LngLatLike, options?: AnimationOptions) => Promise<void>Executes the pan, resolves on moveend
validatePanTarget(lnglat: LngLatLike) => booleanValidates the coordinate shape

Example ​

vue
<script setup>
import { ref } from 'vue';
import { usePanBy, usePanTo } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

const { panBy } = usePanBy({ map: mapInstance, autoPan: false });
const { panTo } = usePanTo({ map: mapInstance, autoPan: false });

await panBy([100, 0], { duration: 500 });
await panTo([106.7, 10.8], { duration: 1000 });
</script>

useRotateTo / useSnapToNorth / useResetNorth / useResetNorthPitch ​

Rotates the map's bearing. useRotateTo rotates to an arbitrary bearing; useSnapToNorth, useResetNorth, and useResetNorthPitch are shortcuts around MapLibre's snapToNorth(), resetNorth(), and resetNorthPitch().

Signature ​

typescript
function useRotateTo(props: RotateToProps): RotateToActions;
function useSnapToNorth(props: SnapToNorthProps): SnapToNorthActions;
function useResetNorth(props: ResetNorthProps): ResetNorthActions;
function useResetNorthPitch(
  props: ResetNorthPitchProps,
): ResetNorthPitchActions;

Parameters ​

All four take a map, animation options and a debug flag. They differ in the target and in the name of the auto-run flag.

useRotateTo

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
bearingnumber—Target bearing in degrees
optionsAnimationOptions—Animation options
autoRotateboolean—Auto-run once the map and bearing are ready; only an explicit false disables it
debugboolean—Enable debug logging

useSnapToNorth

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsAnimationOptions—Animation options
autoSnapboolean—Auto-run once the map is ready; only an explicit false disables it
debugboolean—Enable debug logging

useResetNorth

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsAnimationOptions—Animation options
autoResetboolean—Auto-run once the map is ready; only an explicit false disables it
debugboolean—Enable debug logging

useResetNorthPitch

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsAnimationOptions—Animation options
autoResetboolean—Auto-run once the map is ready; only an explicit false disables it
debugboolean—Enable debug logging

Returns ​

All four return these:

PropertyTypeDescription
stopRotating() => voidStops the in-progress rotation
getCurrentBearing() => number | nullCurrent bearing
getCurrentCamera() => CameraOptions | nullCurrent camera state
rotationStatusComputedRef<RotationStatus>'not-started' | 'rotating' | 'completed' | 'error'
isRotatingComputedRef<boolean>Whether a rotation is in progress

Plus, per composable, the method that runs the rotation:

useRotateTo

PropertyTypeDescription
rotateTo(bearing: number, options?: AnimationOptions) => Promise<void>Rotates to a bearing
validateBearing(bearing: number) => booleanValidates a bearing value

useResetNorth

PropertyTypeDescription
resetNorth(options?: AnimationOptions) => Promise<void>Rotates back to north

useResetNorthPitch

PropertyTypeDescription
resetNorthPitch(options?: AnimationOptions) => Promise<void>Resets both bearing and pitch
getCurrentPitch() => number | nullCurrent pitch

useSnapToNorth

PropertyTypeDescription
snapToNorth(options?: AnimationOptions) => Promise<void>Snaps to north when close enough

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useRotateTo, useResetNorth } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

const { rotateTo } = useRotateTo({ map: mapInstance, autoRotate: false });
const { resetNorth } = useResetNorth({ map: mapInstance, autoReset: false });

await rotateTo(45, { duration: 500 });
await resetNorth({ duration: 500 });
</script>

useZoomIn / useZoomOut / useZoomTo ​

Animates the map's zoom level: useZoomIn/useZoomOut change by one level, useZoomTo zooms to an exact level.

Signature ​

typescript
function useZoomIn(props: ZoomInProps): ZoomInActions;
function useZoomOut(props: ZoomOutProps): ZoomOutActions;
function useZoomTo(props: ZoomToProps): ZoomToActions;

Parameters ​

useZoomTo takes a target level; useZoomIn and useZoomOut step from wherever the map is.

useZoomTo

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
zoomnumber—Target zoom level (0-24)
optionsAnimationOptions—Animation options
autoZoomboolean—Auto-run once the map and zoom are ready; only an explicit false disables it
debugboolean—Enable debug logging

useZoomIn / useZoomOut

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsAnimationOptions—Animation options
autoZoomboolean—Auto-run once the map is ready; only an explicit false disables it
debugboolean—Enable debug logging

Returns ​

PropertyTypeDescription
stopZooming() => voidStops the in-progress zoom
getCurrentZoom() => number | nullCurrent zoom level
getCurrentCamera() => CameraOptions | nullCurrent camera state
zoomStatusComputedRef<ZoomStatus>'not-started' | 'zooming' | 'completed' | 'error'
isZoomingComputedRef<boolean>Whether a zoom is in progress

Plus, per composable, the method that runs the zoom:

useZoomIn

PropertyTypeDescription
zoomIn(options?: AnimationOptions) => Promise<void>Zooms in one level, resolves on zoomend

useZoomOut

PropertyTypeDescription
zoomOut(options?: AnimationOptions) => Promise<void>Zooms out one level, resolves on zoomend

useZoomTo

PropertyTypeDescription
zoomTo(zoom: number, options?: AnimationOptions) => Promise<void>Zooms to a level, resolves on zoomend
validateZoomLevel(zoom: number) => booleanValidates a zoom value (0-24)

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useZoomIn, useZoomOut, useZoomTo } from 'vue3-maplibre-gl';

const mapInstance = ref(null);

const { zoomIn } = useZoomIn({ map: mapInstance, autoZoom: false });
const { zoomOut } = useZoomOut({ map: mapInstance, autoZoom: false });
const { zoomTo } = useZoomTo({ map: mapInstance, autoZoom: false });

await zoomIn({ duration: 300 });
await zoomOut({ duration: 300 });
await zoomTo(14, { duration: 500 });
</script>

useFitBounds / useCameraForBounds ​

useFitBounds moves and zooms the map so a bounding box fits in view (wraps map.fitBounds()). useCameraForBounds only calculates the camera options for a bounding box without moving the map (wraps map.cameraForBounds()) — useful when you want to inspect or tweak the result before applying it.

Signature ​

typescript
function useFitBounds(props: FitBoundsProps): FitBoundsActions;
function useCameraForBounds(
  props: CameraForBoundsProps,
): CameraForBoundsActions;

Parameters ​

Both take a map and a debug flag; only the options type differs.

useFitBounds

PropertyTypeDescription
mapMaybeRef<Map | null>Map instance reference
optionsFitBoundsOptionsFit options, e.g. padding
debugbooleanEnable debug logging

useCameraForBounds

PropertyTypeDescription
mapMaybeRef<Map | null>Map instance reference
optionsCameraForBoundsOptions & { bounds?: LngLatBoundsLike }Camera options, e.g. padding
debugbooleanEnable debug logging

Returns ​

useFitBounds

PropertyTypeDescription
setFitBounds(bounds: LngLatBoundsLike, options?: FitBoundsOptions) => voidFits the map to the given bounds
clearBounds() => voidResets internal bounds state
getCurrentBounds() => LngLatBounds | nullCurrent map bounds
boundsComputedRef<LngLatBoundsLike | undefined>Last bounds applied
boundsStatusComputedRef<BoundsStatus>'not-set' | 'setting' | 'set' | 'error'
isBoundsSetComputedRef<boolean>Whether bounds are currently set

useCameraForBounds

PropertyTypeDescription
cameraForBounds(bounds: LngLatBoundsLike, options?: CameraForBoundsOptions) => voidCalculates camera options for bounds
clearCamera() => voidResets internal state
getCurrentBounds() => LngLatBounds | nullCurrent map bounds
bboxComputedRef<LngLatBoundsLike | undefined>Last bounding box used
cameraStatusComputedRef<BoundsStatus>'not-set' | 'setting' | 'set' | 'error'
isCameraSetComputedRef<boolean>Whether a camera was computed

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useFitBounds } from 'vue3-maplibre-gl';

const mapInstance = ref(null);
const { setFitBounds } = useFitBounds({ map: mapInstance });

setFitBounds(
  [
    [-74.0, 40.7], // Southwest
    [-73.9, 40.8], // Northeast
  ],
  { padding: 20, duration: 1000 },
);
</script>

useFitScreenCoordinates ​

Fits the map to a rectangle defined by screen pixel coordinates (rather than geographic bounds) — wraps map.fitScreenCoordinates(). Handy for "draw a box on screen to zoom into it" UI.

Signature ​

typescript
function useFitScreenCoordinates(
  props: FitScreenCoordinatesProps,
): FitScreenCoordinatesActions;

Parameters (FitScreenCoordinatesProps) ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
defaultOptionsOmit<FitBoundsOptions, 'bearing'>—Default fit options
defaultBearingnumber—Default bearing to use if none is passed
autoCleanupbooleantrueClear coordinates on unmount
debugbooleanfalseEnable debug logging

Returns ​

PropertyTypeDescription
fitScreenCoordinates(p0: PointLike, p1: PointLike, options?, bearing?) => voidFits the map to the pixel rectangle
clearCoordinates() => voidClears the current selection
statusComputedRef<FitScreenCoordinatesStatus>'not-set' | 'setting' | 'set' | 'error'
isCoordinatesSetComputedRef<boolean>Whether both points are set
isFittingComputedRef<boolean>Whether the fit is in progress
hasErrorComputedRef<boolean>Whether the last fit failed

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useFitScreenCoordinates } from 'vue3-maplibre-gl';

const mapInstance = ref(null);
const { fitScreenCoordinates } = useFitScreenCoordinates({ map: mapInstance });

// User drew a selection box from (50,50) to (300,300) pixels
fitScreenCoordinates([50, 50], [300, 300]);
</script>

Utility Composables ​

useFlyTo ​

Provides smooth animated transitions to new map positions with customizable easing and duration.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsFlyToOptions—Default options for every call
debugbooleanundefinedEnable debug logging; omitted logs nothing

Returns ​

PropertyTypeDescription
flyTo(options?: FlyToOptions) => Promise<void>Execute fly-to animation
flyToCenter(center, options?) => Promise<void>Fly, changing only the center
flyToZoom(zoom, options?) => Promise<void>Fly, changing only the zoom
flyToBearing(bearing, options?) => Promise<void>Fly, changing only the bearing
flyToPitch(pitch, options?) => Promise<void>Fly, changing only the pitch
stopFlying() => voidInterrupt the running animation
getCurrentCamera() => CameraOptions | nullRead the camera as it is now
flyStatusComputedRef<FlyStatus>Current animation status
isFlyingComputedRef<boolean>Whether animation is active
cleanup() => voidRelease listeners early

Each flyTo* resolves when the animation settles, so they can be awaited.

Example ​

typescript
import { ref } from 'vue';
import { useFlyTo } from 'vue3-maplibre-gl';

const mapInstance = ref<Map | null>(null);

const { flyTo, isFlying } = useFlyTo({
  map: mapInstance,
});

// Fly to a new location
flyTo({
  center: [0, 0],
  zoom: 10,
  duration: 2000,
  essential: true,
});

// Check if animation is active
watch(isFlying, (flying) => {
  console.log('Animation active:', flying);
});

useEaseTo ​

Provides smooth animated transitions with easing functions for map camera changes.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsEaseToOptions—Default options for every call
debugbooleanundefinedEnable debug logging; omitted logs nothing

Returns ​

PropertyTypeDescription
easeTo(options?: EaseToOptions) => Promise<void>Ease with the given options
easeToCenter(center: LngLatLike, options?) => Promise<void>Ease to a centre
easeToZoom(zoom: number, options?) => Promise<void>Ease to a zoom level
easeToBearing(bearing: number, options?) => Promise<void>Ease to a bearing
easeToPitch(pitch: number, options?) => Promise<void>Ease to a pitch
stopEasing() => voidStop the animation in place
getCurrentCamera() => CameraOptions | nullRead the camera as it is now
easeStatusComputedRef<EaseStatus>Current animation status
isEasingComputedRef<boolean>Whether an animation is running

The same shape as useFlyTo with ease in place of fly, minus cleanup. Each easeTo* resolves when the animation settles.

Example ​

typescript
import { useEaseTo } from 'vue3-maplibre-gl';

const { easeTo, isEasing } = useEaseTo({
  map: mapInstance,
});

// Ease to a new position
easeTo({
  center: [0, 0],
  zoom: 12,
  bearing: 45,
  pitch: 30,
  duration: 1000,
});

useJumpTo ​

Provides instant map position changes without animation.

Parameters ​

PropertyTypeDefaultDescription
mapMaybeRef<Map | null>—Map instance reference
optionsJumpToOptions—Default options for every call
autoJumpbooleanundefinedJump as soon as the map is available; only an explicit false disables it
debugbooleanundefinedEnable debug logging; omitted logs nothing

Returns ​

PropertyTypeDescription
jumpTo(options?: JumpToOptions) => voidExecute instant position change
jumpToCenter(center, options?) => voidJump, changing only the center
jumpToZoom(zoom, options?) => voidJump, changing only the zoom
jumpToBearing(bearing, options?) => voidJump, changing only the bearing
jumpToPitch(pitch, options?) => voidJump, changing only the pitch
getCurrentCamera() => CameraOptions | nullRead the camera as it is now
validateJumpOptions(options: JumpToOptions) => booleanCheck options before jumping
jumpStatusComputedRef<JumpStatus>Current jump status
isJumpingComputedRef<boolean>Whether a jump is in progress

Example ​

typescript
import { useJumpTo } from 'vue3-maplibre-gl';

const { jumpTo } = useJumpTo({
  map: mapInstance,
});

// Jump to a new position instantly
jumpTo({
  center: [0, 0],
  zoom: 15,
  bearing: 0,
  pitch: 0,
});

useLogger ​

Provides consistent logging functionality with debug level control.

Parameters ​

ParameterTypeDescription
debugbooleanWhether to enable debug logging

Returns ​

PropertyTypeDescription
log(message: string, ...args: any[]) => voidLog debug message
logError(message: string, ...args: any[]) => voidLog error message
logWarn(message: string, ...args: any[]) => voidLog warning message

Example ​

typescript
import { useLogger } from 'vue3-maplibre-gl';

const { log, logError, logWarn } = useLogger(true);

// Log debug information
log('Map initialized successfully');

// Log errors
logError('Failed to load map style:', error);

// Log warnings
logWarn('Deprecated API usage detected');

Performance Composables ​

Generic, map-agnostic helpers for debouncing and optimizing reactive computations. Useful when a map event (e.g. move, mousemove) fires faster than you want to react to it.

useDebounce ​

Wraps a plain function so it only runs after a delay of no further calls (or on a leading/trailing edge, lodash-debounce style). Great for wrapping expensive handlers on high-frequency map events like move or mousemove.

Signature ​

typescript
function useDebounce<T extends (...args: any[]) => any>(
  func: T,
  options?: DebounceOptions,
): DebouncedFunction<T>;

Parameters (DebounceOptions) ​

PropertyTypeDefaultDescription
delaynumber300Delay in milliseconds
leadingbooleanfalseInvoke on the leading edge of the delay
trailingbooleantrueInvoke on the trailing edge of the delay
maxWaitnumber—Force invocation after this many ms even if still being called
debugbooleanfalseEnable debug logging

Returns ​

A DebouncedFunction<T> — call it like the original function; it also exposes:

PropertyTypeDescription
cancel() => voidCancel any pending invocation
flush() => voidInvoke immediately if one is pending
pending() => booleanWhether an invocation is pending

Example ​

vue
<script setup>
import { useDebounce } from 'vue3-maplibre-gl';

const logMove = useDebounce(
  (center) => {
    console.log('Map moved to:', center);
  },
  { delay: 300 },
);

// call logMove(center) inside a 'move' handler — it only logs 300ms after moves stop
</script>

useDebouncedRef ​

Creates a ref pair: write to the "immediate" ref instantly, read a "debounced" ref that only updates after the delay. Useful for search inputs or sliders tied to map operations.

Signature ​

typescript
function useDebouncedRef<T>(
  initialValue: T,
  delay?: number,
): [Ref<T>, Ref<T>, () => void, () => void];

Parameters ​

ParameterTypeDefaultDescription
initialValueT—Initial value for both refs
delaynumber300Debounce delay in milliseconds

Returns ​

A tuple [debouncedRef, immediateRef, flush, cancel]:

IndexNameTypeDescription
0debouncedRefRef<T>Updates delay ms after immediateRef settles
1immediateRefRef<T>Updates instantly when you write to it
2flush() => voidImmediately sync debouncedRef to the latest value
3cancel() => voidCancel the pending update

Example ​

vue
<script setup>
import { useDebouncedRef } from 'vue3-maplibre-gl';

const [debouncedZoom, zoom] = useDebouncedRef(10, 250);

// zoom.value = 12  → updates immediately
// debouncedZoom.value → updates 250ms later, good for triggering expensive layer updates
</script>

useDebouncedWatch ​

Combines Vue's watch with debouncing — the callback only fires delay ms after the watched source stops changing.

Signature ​

typescript
function useDebouncedWatch<T>(
  source: WatchSource<T>,
  callback: (value: T, oldValue: T | undefined) => void,
  options?: DebounceOptions & {
    immediate?: boolean;
    deep?: boolean;
    flush?: 'pre' | 'post' | 'sync';
  },
): () => void;

Parameters ​

ParameterTypeDescription
sourceWatchSource<T>Same as the first argument to Vue's watch
callback(value: T, oldValue: T | undefined) => voidDebounced watch callback
optionsDebounceOptions & { immediate?, deep?, flush? }Debounce options plus standard watch options

Returns ​

() => void — stops both the watcher and any pending debounced call.

Example ​

vue
<script setup>
import { ref } from 'vue';
import { useDebouncedWatch } from 'vue3-maplibre-gl';

const searchQuery = ref('');

useDebouncedWatch(
  searchQuery,
  (query) => {
    console.log('Searching for:', query);
  },
  { delay: 400 },
);
</script>