---
title: "VMarker"
description: "Add interactive markers to your map"
canonical_url: "https://v-maplibre.geoql.in/components/markers"
---
# VMarker

> Add interactive markers to your map

## Usage

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

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

  const markerPosition = { lng: -74.5, lat: 40 };
</script>

<template>
  <VMap :options="mapOptions" style="height: 500px">
    <VMarker :coordinates="markerPosition"></VMarker>
  </VMap>
</template>
```

## Props

### coordinates

- **Type:** `LngLatLike`
- **Required:** `true`

The geographic location of the marker. Can be:

- Object: `{ lng: number, lat: number }`
- Array: `[lng, lat]`
- LngLat instance

```vue
<!-- Object notation -->
<VMarker :coordinates="{ lng: -74.5, lat: 40 }"></VMarker>

<!-- Array notation -->
<VMarker :coordinates="[-74.5, 40]"></VMarker>
```

### draggable

- **Type:** `boolean`
- **Required:** `false`
- **Default:** `false`

Make the marker draggable.

```vue
<VMarker :coordinates="position" draggable @dragend="handleDragEnd"></VMarker>
```

### options

- **Type:** `MarkerOptions`
- **Required:** `false`

Additional MapLibre GL marker options. See [MapLibre GL Marker](https://maplibre.org/maplibre-gl-js/docs/API/classes/Marker/) for all available options.

Common options:

- `color`: Marker color
- `rotation`: Marker rotation in degrees
- `rotationAlignment`: How marker rotates with map
- `pitchAlignment`: How marker aligns with map pitch
- `offset`: Pixel offset from the lngLat position

```vue
<VMarker
  :coordinates="position"
  :options="{
    color: '#FF0000',
    rotation: 45,
    offset: [0, -10],
  }"
></VMarker>
```

## Events

### @click

Emitted when the marker is clicked.

```vue
<VMarker :coordinates="position" @click="handleMarkerClick"></VMarker>
```

### @dragstart

Emitted when marker dragging starts.

```vue
<VMarker :coordinates="position" draggable @dragstart="handleDragStart"></VMarker>
```

### @drag

Emitted continuously while dragging.

```vue
<VMarker :coordinates="position" draggable @drag="handleDrag"></VMarker>
```

### @dragend

Emitted when marker dragging ends.

```vue
<VMarker :coordinates="position" draggable @dragend="handleDragEnd"></VMarker>
```

## Slots

### default

Customize marker HTML content.

```vue
<VMarker :coordinates="position">
  <div class="custom-marker">
    <img src="/marker-icon.png" alt="Custom marker" />
  </div>
</VMarker>
```

## Examples

### Custom Color

```vue
<VMarker :coordinates="[-74.5, 40]" :options="{ color: '#FF5733' }"></VMarker>
```

### Draggable Marker

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

  const position = ref({ lng: -74.5, lat: 40 });

  const handleDragEnd = (event: any) => {
    const lngLat = event.target.getLngLat();
    position.value = { lng: lngLat.lng, lat: lngLat.lat };
    console.log('New position:', position.value);
  };
</script>

<template>
  <VMap :options="mapOptions" style="height: 500px">
    <VMarker :coordinates="position" draggable @dragend="handleDragEnd"></VMarker>
  </VMap>
</template>
```

### Custom Marker with Slot

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

  const position = { lng: -74.5, lat: 40 };
</script>

<template>
  <VMap :options="mapOptions" style="height: 500px">
    <VMarker :coordinates="position">
      <div class="custom-marker">
        <div class="marker-pin"></div>
        <div class="marker-label">Custom Pin</div>
      </div>
    </VMarker>
  </VMap>
</template>

<style scoped>
  .custom-marker {
    position: relative;
    text-align: center;
  }

  .marker-pin {
    width: 30px;
    height: 30px;
    border-radius: 50% 50% 50% 0;
    background: #00cae9;
    transform: rotate(-45deg);
    margin: 0 auto;
  }

  .marker-label {
    position: absolute;
    top: 35px;
    left: 50%;
    transform: translateX(-50%);
    background: white;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 12px;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  }
</style>
```

### Multiple Markers

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

  const locations = [
    { id: 1, lng: -74.5, lat: 40, name: 'Location 1', color: '#FF5733' },
    { id: 2, lng: -74.3, lat: 40.1, name: 'Location 2', color: '#33FF57' },
    { id: 3, lng: -74.4, lat: 39.9, name: 'Location 3', color: '#3357FF' },
  ];
</script>

<template>
  <VMap :options="mapOptions" style="height: 500px">
    <VMarker
      v-for="location in locations"
      :key="location.id"
      :coordinates="[location.lng, location.lat]"
      :options="{ color: location.color }"
      @click="() => console.log('Clicked:', location.name)"
    ></VMarker>
  </VMap>
</template>
```


## Sitemap

See the full [sitemap](https://v-maplibre.geoql.in/sitemap.md) for all pages.
