MapboxMap

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

简介

MapboxMap 是一切的根组件:它在客户端 onMounted 创建 mapbox-gl 实例,经 provide 下发 MapboxContext,子组件经 useMap() 取用。容器宽高为 100%,请确保父级有明确高度(示例统一用 h-115)。

组件已做 SSR 安全处理,无需 <ClientOnly> 包裹;accessToken 省略时回退到模块注入的全局 token。

用法

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

<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>

示例

相机切换

useMapboxCameraflyTo 在多个预设机位间平滑切换:

<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.23], 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

Prop Default Type
mapIdstring

地图 id;省略时自动生成。提供后可经 useMapbox(id) 外部访问

optionsMapboxMapOptions

mapbox-gl Map 初始化选项(container 由组件接管)

accessTokenstring

覆盖全局 access token

centermapboxgl.LngLat | { lng: number; lat: number; } | { lon: number; lat: number; } | [number, number]
zoomnumber
bearingnumber
pitchnumber
persistentfalseboolean

卸载时不销毁实例,配合 keepalive / <keep-alive> 跨路由复用

Emits

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

Event Type
update:center[value: mapboxgl.LngLatLike]
update:zoom[value: number]
update:bearing[value: number]
update:pitch[value: number]
load[map: mapboxgl.Map]
idle[map: mapboxgl.Map]
error[event: { type: "error"; target: mapboxgl.Map; } & { error: Error; }]
click[event: mapboxgl.MapMouseEvent]
dblclick[event: mapboxgl.MapMouseEvent]
contextmenu[event: mapboxgl.MapMouseEvent]
mousemove[event: mapboxgl.MapMouseEvent]
mousedown[event: mapboxgl.MapMouseEvent]
mouseup[event: mapboxgl.MapMouseEvent]
movestart[event: { type: "movestart"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | WheelEvent | TouchEvent; }]
moveend[event: { type: "moveend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | WheelEvent | TouchEvent; }]
zoomstart[event: { type: "zoomstart"; target: mapboxgl.Map; }]
zoomend[event: { type: "zoomend"; target: mapboxgl.Map; }]
rotateend[event: { type: "rotateend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent; }]
pitchend[event: { type: "pitchend"; target: mapboxgl.Map; }]
dragend[event: { type: "dragend"; target: mapboxgl.Map; } & { originalEvent?: MouseEvent | TouchEvent; }]
styledata[event: { type: "styledata"; target: mapboxgl.Map; } & mapboxgl.MapStyleDataEvent]
sourcedata[event: { type: "sourcedata"; target: mapboxgl.Map; } & mapboxgl.MapSourceDataEvent]

Slots

Slot Type
default{}

Changelog

No recent changes
Copyright © 2026 - 2026 YiXuan - MIT License