---
title: "MapboxPopup"
description: "弹窗，默认插槽渲染内容，lnglat 锚定且响应式更新位置。"
seo_title: "MapboxPopup Component"
seo_description: "MapboxPopup anchors a mapbox-gl popup at a reactive lnglat, rendering arbitrary content through its default slot and emitting close."
canonical_url: "https://mapbox.mhaibaraai.cn/docs/core/popup"
---
# MapboxPopup

> 弹窗，默认插槽渲染内容，lnglat 锚定且响应式更新位置。

## 简介

`MapboxPopup` 在指定 `lnglat` 锚定一个弹窗，默认插槽渲染任意内容；`lnglat` 变更时响应式更新位置，关闭时触发 `close` 事件。

## 用法

默认插槽渲染弹窗内容，`options.closeOnClick` 等选项透传给 mapbox：

```vue [PopupBasicExample.vue]
<script setup lang="ts">
import type { LngLatLike } from 'mapbox-gl'

const lnglat = ref<LngLatLike>([116.397, 39.908])
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap :options="{ style: 'mapbox://styles/mapbox/streets-v12', center: [116.397, 39.908], zoom: 13 }">
      <!-- 默认插槽渲染弹窗内容 -->
      <MapboxPopup :lnglat="lnglat" :options="{ closeOnClick: false, offset: 12 }">
        <div class="px-1 py-0.5">
          <p class="font-semibold">
            天安门
          </p>
          <p class="text-sm text-muted">
            北京市东城区
          </p>
        </div>
      </MapboxPopup>
    </MapboxMap>
  </div>
</template>
```

## 示例

### 点击设置位置

点击地图取坐标并赋给 `lnglat`，弹窗随之定位：

```vue [PopupClickExample.vue]
<script setup lang="ts">
import type { LngLatLike, MapEventOf } from 'mapbox-gl'

const lnglat = ref<LngLatLike | null>(null)
const label = ref('')

// 点击地图取坐标，弹窗随之定位（同一 Popup 经 watch 增量更新位置）
function onClick(event: MapEventOf<'click'>) {
  const { lng, lat } = event.lngLat
  lnglat.value = [lng, lat]
  label.value = `${lng.toFixed(4)}, ${lat.toFixed(4)}`
}
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap
      :options="{ style: 'mapbox://styles/mapbox/streets-v12', center: [116.397, 39.908], zoom: 12 }"
      @click="onClick"
    >
      <MapboxPopup v-if="lnglat" :lnglat="lnglat" :options="{ offset: 8 }">
        <div class="px-1 py-0.5 text-sm">
          {{ label }}
        </div>
      </MapboxPopup>
      <div v-if="!lnglat" class="absolute left-3 top-3 z-10 rounded-(--ui-radius) border border-default bg-default/80 px-3 py-1.5 text-sm backdrop-blur">
        点击地图任意位置
      </div>
    </MapboxMap>
  </div>
</template>
```

### 多弹窗共存

`v-for` 渲染多个 `MapboxPopup` 即可让一组点位的弹窗同时常驻。`closeOnClick` 必须关掉，否则任意一次地图点击会把整组弹窗一并关闭：

```vue [PopupGroupExample.vue]
<script setup lang="ts">
interface Poi {
  id: string
  lnglat: [number, number]
  name: string
}

const points: Poi[] = [
  { id: 'tam', lnglat: [116.397, 39.908], name: '天安门' },
  { id: 'gm', lnglat: [116.461, 39.909], name: '国贸' },
  { id: 'zgc', lnglat: [116.316, 39.983], name: '中关村' }
]
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap :options="{ style: 'mapbox://styles/mapbox/light-v11', center: [116.39, 39.94], zoom: 10.6 }">
      <MapboxPopup
        v-for="point in points"
        :key="point.id"
        :lnglat="point.lnglat"
        :options="{ closeButton: false, closeOnClick: false, offset: 12 }"
      >
        <div class="px-1 text-sm font-semibold">
          {{ point.name }}
        </div>
      </MapboxPopup>
    </MapboxMap>
  </div>
</template>
```

> \[\!NOTE\]
> 
> MapboxTooltip
> 
>  内部只有一个 Popup 实例，无法同时展开多个要素的弹窗；它的 
> 
> feature
> 
>  来自鼠标事件，组件并不持有要素列表。要让图层要素的弹窗同时常驻，请直接用构造 GeoJSON 的源数组 
> 
> v-for
> 
>  出多个 
> 
> MapboxPopup
> 
> 。若点位是 DOM 标记，用 
> 
> MapboxMarker
> 
>  的 
> 
> :open="true"
> 
>  更直接。

## API

### Props

```ts
/**
 * Props for the MapboxPopup component
 */
interface MapboxPopupProps {
  /**
   * 弹窗锚定的经纬度
   */
  lnglat: mapboxgl.LngLatLike;
  /**
   * Popup 选项
   */
  options?: mapboxgl.PopupOptions | undefined;
}
```

### Emits

```ts
/**
 * Emitted events for the MapboxPopup component
 */
interface MapboxPopupEmits {
  close: (payload: []) => void;
}
```

### Slots

```ts
/**
 * Slots for the MapboxPopup component
 */
interface MapboxPopupSlots {
  default(): any;
}
```

### Expose

通过 [`useTemplateRef`](https://vuejs.org/api/composition-api-helpers.html#usetemplateref){rel="[\"nofollow\"]"} 访问组件实例。

| Name    | Type                                                  |
| ------- | ----------------------------------------------------- |
| `popup` | `() => Popup | undefined`   
 获取底层 mapbox-gl Popup 实例 |

## Changelog

See commit history for [src/runtime/components/MapboxPopup.vue](https://github.com/mhaibaraai/movk-mapbox/commits/main/src/runtime/components/MapboxPopup.vue).


## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
