---
title: "MapboxMap"
description: "根组件，在客户端创建 Mapbox GL 实例并经 MapboxContext 下发，支持相机 v-model 双向绑定与跨路由持久化。"
seo_title: "MapboxMap Component"
seo_description: "MapboxMap is the root component that creates a mapbox-gl instance on the client and provides MapboxContext to descendants, with v-model camera binding, persistent reuse and SSR-safe rendering."
canonical_url: "https://mapbox.mhaibaraai.cn/docs/core/map"
---
# MapboxMap

> 根组件，在客户端创建 Mapbox GL 实例并经 MapboxContext 下发，支持相机 v-model 双向绑定与跨路由持久化。

## 简介

`MapboxMap` 是一切的根组件：它在客户端 `onMounted` 创建 `mapbox-gl` 实例，经 `provide` 下发 [MapboxContext](/docs/getting-started/concepts)，子组件经 `useMap()` 取用。容器宽高为 `100%`，请确保父级有明确高度（示例统一用 `h-115`）。

> \[\!NOTE\]
> 
> 组件已做 SSR 安全处理，无需 
> 
> <ClientOnly>
> 
>  包裹；
> 
> accessToken
> 
>  省略时回退到模块注入的全局 token。

> \[\!NOTE\]
> 
> hideLogo
> 
>  仅隐藏左下角的 Mapbox 字标，不影响右下角归属信息（归属信息经 
> 
> options.attributionControl
> 
>  或 
> 
> MapboxAttributionControl
> 
>  控制）。该开关面向自有或第三方底图（如天地图）；使用 Mapbox 官方底图与数据时，署名展示须遵守 Mapbox 服务条款。

## 用法

`center` / `zoom` / `bearing` / `pitch` 支持 `v-model`：组件与地图现值比对、有差异才下发，从而断开「模型 → 地图 → 事件 → 模型」回环。拖动或缩放地图，绑定值随之更新。

```vue [MapBasicExample.vue]
<script setup lang="ts">
const center = ref<[number, number]>([116.397, 39.908])
const zoom = ref(9)
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap
      v-model:center="center"
      v-model:zoom="zoom"
      :options="{ style: 'mapbox://styles/mapbox/streets-v12' }"
    >
      <MapboxNavigationControl position="top-right" />
    </MapboxMap>
  </div>
</template>
```

## 示例

### 相机切换

经 `useMapboxCamera` 的 `flyTo` 在多个预设机位间平滑切换：

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

const mapId = 'camera-demo'
const { flyTo } = useMapboxCamera({ mapId })

const presets: { label: string, center: LngLatLike, zoom: number }[] = [
  { label: 'Beijing', center: [116.397, 39.908], zoom: 10 },
  { label: 'Shanghai', center: [121.473, 31.230], zoom: 10 },
  { label: 'Shenzhen', center: [114.057, 22.543], zoom: 10 }
]

function go(center: LngLatLike, zoom: number) {
  flyTo({ center, zoom, duration: 2000 })
}
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap
      :map-id="mapId"
      :options="{ style: 'mapbox://styles/mapbox/streets-v12', center: [116.397, 39.908], zoom: 10 }"
    >
      <div class="absolute left-3 top-3 z-10 flex flex-wrap gap-2">
        <UButton
          v-for="p in presets"
          :key="p.label"
          size="xs"
          color="neutral"
          variant="solid"
          @click="go(p.center, p.zoom)"
        >
          {{ p.label }}
        </UButton>
      </div>
    </MapboxMap>
  </div>
</template>
```

## API

### Props

```ts
/**
 * Props for the MapboxMap component
 */
interface MapboxMapProps {
  /**
   * 地图 id；省略时自动生成。提供后可经 useMapbox(id) 外部访问
   */
  mapId?: string | undefined;
  /**
   * mapbox-gl Map 初始化选项（container 由组件接管）
   */
  options?: MapboxMapOptions | undefined;
  /**
   * 覆盖全局 access token
   */
  accessToken?: string | undefined;
  /**
   * 卸载时不销毁实例，配合 keepalive / `<keep-alive>` 跨路由复用
   * @default "false"
   */
  persistent?: boolean | undefined;
  /**
   * 隐藏地图左下角的 Mapbox 字标
   * @default "false"
   */
  hideLogo?: boolean | undefined;
  center?: mapboxgl.LngLatLike | undefined;
  zoom?: number | undefined;
  bearing?: number | undefined;
  pitch?: number | undefined;
}
```

### Emits

`update:center` / `update:zoom` / `update:bearing` / `update:pitch` 为相机 `v-model` 同步事件，其余为透传的 mapbox-gl 地图事件。

```ts
/**
 * Emitted events for the MapboxMap component
 */
interface MapboxMapEmits {
  click: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  contextmenu: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  dblclick: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  dragend: (payload: [event: { type: "dragend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent | undefined; }]) => void;
  error: (payload: [event: { type: "error"; target: mapboxgl.Map; } & { error: Error; }]) => void;
  load: (payload: [map: mapboxgl.Map]) => void;
  mousedown: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  mousemove: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  mouseup: (payload: [event: mapboxgl.MapMouseEvent]) => void;
  update:center: (payload: [value: mapboxgl.LngLatLike | undefined]) => void;
  update:zoom: (payload: [value: number | undefined]) => void;
  update:bearing: (payload: [value: number | undefined]) => void;
  update:pitch: (payload: [value: number | undefined]) => void;
  idle: (payload: [map: mapboxgl.Map]) => void;
  movestart: (payload: [event: { type: "movestart"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent | WheelEvent | undefined; }]) => void;
  moveend: (payload: [event: { type: "moveend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent | WheelEvent | undefined; }]) => void;
  zoomstart: (payload: [event: { type: "zoomstart"; target: mapboxgl.Map; }]) => void;
  zoomend: (payload: [event: { type: "zoomend"; target: mapboxgl.Map; }]) => void;
  rotateend: (payload: [event: { type: "rotateend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent | undefined; }]) => void;
  pitchend: (payload: [event: { type: "pitchend"; target: mapboxgl.Map; }]) => void;
  styledata: (payload: [event: { type: "styledata"; target: mapboxgl.Map; } & mapboxgl.MapStyleDataEvent]) => void;
  sourcedata: (payload: [event: { type: "sourcedata"; target: mapboxgl.Map; } & mapboxgl.MapSourceDataEvent]) => void;
}
```

### Slots

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

## Changelog

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


## Sitemap

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