Skip to content

Map

Interaction: Left-click and drag to pan, right-click to change the perspective (tilt/rotate).

TIP

When displaying text on the map, be sure to set the glyphs property.

TIP

If you need to customize the coordinate system, the crs parameter format is string or array: [name, wkt, extent];

  • name: The name of the coordinate system (required).
  • wkt: The WKT (Well-Known Text) or Proj4 representation of the coordinate system (required).
  • extent: The extent of the current coordinate system, [left, bottom, right, top].

Basic

center:[ 116.3466, 39.8704 ] zoom:8

bearing:0 pitch:0

mouse position:



Example Source Code
vue
<template>
  <div style="height: 500px" class="vw-full vh-full">
    <div style="height: 400px">
      <mb-map
        ref="mapInst"
        v-model:zoom="mapZoom"
        v-model:center="mapCenter"
        v-model:bearing="bearing"
        v-model:pitch="pitch"
        @mousemove="mouseMoveHandler"
      >
        <div style="position: absolute; top: 10px; left: 10px">
          <button class="primary mr10" @click="easeToRandomPos">
            ease to some position
          </button>
          <button class="primary" @click="flyToRandomPos">
            fly to some position
          </button>
        </div>
        <mb-tianditu-layer />
      </mb-map>
      <div style="height: 60px; margin: 10px 0px">
        <p class="text-muted">center:{{ mapCenter }} zoom:{{ mapZoom }}</p>
        <p class="text-muted">bearing:{{ bearing }} pitch:{{ pitch }}</p>
        <p class="text-muted">mouse position:{{ mousePosition }}</p>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { MapInstance } from '@mapbox-vue3/core'

const mapInst = ref<MapInstance>()
const mapCenter = ref([116.3466, 39.8704])
const mapZoom = ref(8)
const bearing = ref(0)
const pitch = ref(0)
const mousePosition = ref('')

const mouseMoveHandler = (movement) => {
  mousePosition.value = movement.coordinates
}
const easeToRandomPos = () => {
  mapInst.value
    ?.easeTo({
      center: [
        mapCenter.value[0] + getRandomArbitrary(-1, 1),
        mapCenter.value[1] + getRandomArbitrary(-1, 1),
      ],
      duration: 2000,
    })
    .then(() => {
      // callback after over
    })
}
const flyToRandomPos = () => {
  mapInst.value
    ?.flyTo({
      center: [getRandomArbitrary(-180, 180), getRandomArbitrary(-90, 90)],
      zoom: getRandomArbitrary(0, 18),
    })
    .then(() => {
      // callback after over
    })
}

function getRandomArbitrary(min: number, max: number) {
  return Math.random() * (max - min) + min
}
</script>

Layer Reordering

Example Source Code
vue
<template>
  <div style="height: 500px" class="vw-full vh-full">
    <div style="height: 400px">
      <mb-map ref="mapInst" :zoom="mapZoom" :center="mapCenter">
        <mb-image-loader :images="images" />
        <mb-image-frame-loader :images="images2" />
        <div style="position: absolute; top: 10px; left: 10px">
          <button
            class="primary mr10"
            @click="reorder(['buffer2', 's3', 'buffer1', 's2', 's1'])"
          >
            Order:buffer2, s3, buffer1, s2, s1(top)
          </button>
          <button
            class="primary"
            @click="reorder(['s2', 's3', 's1', 'buffer2', 'buffer1'])"
          >
            Order:s2, s3, s1, buffer2, buffer1(top)
          </button>
        </div>
        <mb-tianditu-layer />
        <mb-symbol-layer
          id="s1"
          :data="symbolDataSource"
          text-field="label"
          icon-image-field="icon"
          :icon-size="0.5"
          :text-offset="[0, -1]"
          icon-allow-overlap
          text-allow-overlap
        />
        <mb-buffer-ellipse-layer
          id="buffer1"
          :center="mapCenter"
          :x-semi-axis="10"
          :y-semi-axis="5"
          :angle="0"
          border-color="red"
          :border-opacity="0.5"
          background-color="red"
          center-color="red"
          center-radius="6"
          resizer-color="green"
          resizer-radius="6"
          rotater-color="black"
          :background-opacity="0.1"
          :closable="true"
          :countable="true"
          :draggable="true"
          :resizable="true"
          :rotatable="true"
        />
        <mb-symbol-layer
          id="s2"
          :data="symbolDataSource2"
          text-field="label"
          icon-image-field="icon"
          :icon-size="0.5"
          :text-offset="[0, -1]"
          :cluster="true"
          :spiderify="true"
          :cluster-mamb-zoom="18"
          icon-allow-overlap
          text-allow-overlap
        />
        <mb-symbol-layer
          id="s3"
          :data="symbolDataSource3"
          text-field="label"
          icon-image-field="icon"
          :icon-size="0.5"
          :text-offset="[0, -1]"
          icon-allow-overlap
          text-allow-overlap
        />
        <mb-buffer-sector-layer
          id="buffer2"
          :polygon="polygon"
          :radius="7"
          :center="mapCenter"
          border-color="red"
          :border-opacity="0.5"
          background-color="red"
          center-color="red"
          resizer-color="blue"
          :background-opacity="0.1"
          :closable="true"
          :countable="true"
          :draggable="true"
          :resizable="true"
          :rotatable="true"
        />
      </mb-map>
    </div>
  </div>
</template>
<script setup lang="ts">
import { onBeforeMount, ref } from 'vue'
import type { MapInstance } from '@mapbox-vue3/core/es'

type SymbolLayerData = Array<{
  coordinates: number[]
  properties?: Record<string, any>
}>

const mapInst = ref<MapInstance>()
const mapCenter = ref([116.3466, 39.8704])
const mapZoom = ref(10)
const symbolDataSource = ref<SymbolLayerData>([])
const symbolDataSource2 = ref<SymbolLayerData>([])
const symbolDataSource3 = ref<SymbolLayerData>([])
const polygon = [
  [116.17381, 39.92155464],
  [116.25105956968257, 40.02398993628292],
  [116.31591012802686, 39.96769599504311],
]
const images = [
  {
    name: 'event',
    type: 'link',
    url: `${__RESOURCE_URL__}images/common_toget.png`,
  },
  {
    name: 'event2',
    type: 'link',
    url: `${__RESOURCE_URL__}images/eme_team_soc_toget.png`,
  },
]
const images2 = [
  {
    name: 'event3',
    dir: 'v',
    steps: 3,
    duration: 300,
    url: `${__RESOURCE_URL__}images/v-steps.png`,
  },
]

const reorder = (layerIds: string[]) => {
  mapInst.value?.reorderLayers(layerIds)
}

onBeforeMount(() => {
  symbolDataSource.value = [
    {
      coordinates: [116.45346681596038, 39.90085772830014],
      properties: {
        icon: 'event',
      },
    },
    {
      coordinates: [...mapCenter.value],
      properties: {
        icon: 'event',
      },
    },
  ]
  symbolDataSource2.value = [
    {
      coordinates: [116.46346681596, 39.90085772830014],
      properties: {
        icon: 'event2',
      },
    },
    {
      coordinates: [...mapCenter.value],
      properties: {
        icon: 'event2',
      },
    },
  ]
  symbolDataSource3.value = [
    {
      coordinates: [116.47346681596038, 39.94085772830014],
      properties: {
        icon: 'event3',
        iconSize: 0.1,
      },
    },
    {
      coordinates: [...mapCenter.value],
      properties: {
        icon: 'event3',
        iconSize: 0.1,
      },
    },
  ]
})
</script>

Obtaining the Map Instance

Generally, you can obtain the MbMap instance using a ref. You can obtain the encapsulated mapbox instance by listening to the created event of MbMap.

  • If your component can be placed inside the MbMap component, you can use the useMapCreated hook provided by the component library to get the map instance.
demo3.vue
vue
<template>
  <div style="height: 400px" class="vw-full vh-full">
    <mb-map>
      <instance1 />
    </mb-map>
  </div>
</template>

<script setup lang="ts">
import Instance1 from './instance1.vue'
</script>
instance1.vue
vue
<script lang="ts" setup>
import { useMapCreated } from '@mapbox-vue3/core'

const init = () => {
  const map = getMapInstance()
  const mapbox = getMapboxInstance()
  console.log(map, mapbox)
}

const { getMapInstance, getMapboxInstance } = useMapCreated(init)
</script>
  • If you want to interact with the map in other components, such as manipulating ThreeJS, you can declare a global variable, then listen to the created event and store the Mapbox map instance. Use this instance to operate the map when needed. Below is a partial code example:
ts
// use-map.ts
import type { MapboxInstance } from '@mapbox-vue3/core'


let mapbox: MapboxInstance

function useMap() {
  const onCreated = (mb: MapboxInstance) => {
    console.log('map created', mb)
    mapbox = mb
  }

  // Remember to destroy when no longer needed
  const destroy = () => {
    mapbox = null
  }

  return {
    onCreated,
    destroy,
    // It's important to write this as a method. Directly returning `mapbox` will always result in `undefined`
    getMapbox: () => mapbox
  }
}

export { useMap }
vue
<template>
  <MbMap
    ...
    @created="onCreated"
  />
</template>
<script setup lang="ts">
import { useMap } from './use-map'

const { onCreated } = useMap()
</script>

In the place where you need to use it:

vue
<script lang="ts">
import { useMap } from './use-map'

const { getMapbox } = useMap()
</script>

The above method has a problem: you can only use the getMapbox method to get the instance after the map instance is created. Otherwise, the obtained instance will be undefined.

  • If your code logic cannot determine whether the map has finished creating when operating the map, you need to use a slightly more complex method for map operations. Below is a code example:

You need to install the ts-deferred utility library:

ts
// map-deferred.ts
import { Deferred } from 'ts-deferred';

const defferedMap = new Deferred<void>();

const waitingForMap = async() => {
  return await defferedMap.promise;
};
const resolveMap = () => {
  defferedMap.resolve();
};

export { waitingForMap, resolveMap };
ts
// use-map.ts
import { resolveMap } from './map-deferred'
import type { MapboxInstance } from '@mapbox-vue3/core'

let mapbox: MapboxInstance

function useMap() {
  const onCreated = (mb: MapboxInstance) => {
    console.log('map created', mb)
    mapbox = mb
    resolveMap()
  }

  // Remember to destroy when no longer needed
  const destroy = () => {
    mapbox = null
  }

  return {
    onCreated,
    destroy,
    // It's important to write this as a method. Directly returning `mapbox` will always result in `undefined`
    getMapbox: () => mapbox
  }
}

export { useMap }
vue
// instance.vue
<script lang="ts" setup>
import { onMounted } from 'vue'
import { useMap } from './use-map'
import { waitingForMap } from './map-deferred'

const { getMapbox } = useMap()

onMounted(async() => {
  await waitingForMap()
  // Now you can use getMapbox() to get the map instance for operations
  console.log('operate', getMapbox())
})

</script>
vue
<template>
  <MbMap
    ...
    @created="onCreated"
  />
  <instance />
</template>
<script setup lang="ts">
import { useMap } from './use-map'
import Instance from './instance.vue'

const { onCreated } = useMap()
</script>

API

PROPS

NameDescriptionTypeDefault
antialiasWhether to enable antialiasing; disabling it can improve performancebooleantrue
bearingv-model The initial bearing (rotation angle) of the mapnumber0
boundsThe initial bounding box of the map. If bounds is set, it will override the center and zoom settings. Its value is the southwest and northeast points of a rectangle, for example: [[-73.9876, 40.7661], [-73.9397, 40.8002]]IndexAny / AnyArrundefined
centerv-model The geographic center point of the map, using the order of longitude, latitudenumber[][116.38745, 39.91266]
map-styleMap style information, including font file paths and sprite image pathsIndexAny / string{ version: 8, sources: {}, layers: [], glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', sprite: "mapbox://sprites/mapbox/bright-v8" }
glyphsPath to the font files. Can be set separately and will override the value in mapStylestring-
spritePath to the sprite image. Can be set separately and will override the value in mapStylestring-
max-boundsAfter being set, the map will be restricted to the given maximum boundsIndexAny / AnyArrundefined
maxzoomMaximum zoom level of the mapnumber22
minzoomMinimum zoom level of the mapnumber0
pitchv-model The initial pitch of the mapnumber0
zoomv-model The zoom level of the mapnumber2
hashWhether the map's location information is synchronized to the browser URL hashboolean / stringfalse
interactiveWhether the map is interactivebooleantrue
crsCoordinate Reference System, with lower priority than extendPropsstring / AnyArr-
extend-propsExtended properties. See the Mapbox documentationIndexAny{}

extendProps Explanation

All parameters of the Mapbox official documentation's map creation interface can be passed through this property. It has higher priority than all other properties in the Map component.

TIP

Except for the four properties that can be used with v-model, all other properties are non-reactive. If you need to modify them, you can get the map object through the created event parameter and then call the Mapbox native API.

EVENTS

名称描述参数
createdEvent triggered when the map is initializedmap: MapboxInstance
update:zoomEvent triggered when the map's zoom level changesnumber
update:centerEvent triggered when the map's center changesnumber[]
update:bearingEvent triggered when the map's bearing changesnumber
update:pitchEvent triggered when the map's pitch changesnumber
clickMouse click event. Triggered on every clickobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
dblclickMouse double-click eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
singleclickMouse single-click eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
mousemoveMouse move eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
mouseoutMouse leaves the map areaMapMouseEvent & EventData

SLOTS

NameDescription
defaultDefault slot

METHODS

NameDescriptionDefinition
moveLayerMoves a layer to a position before the layer represented by beforeId. If beforeId is empty, the layer is moved to the end of the layer list (the top layer of the map)id: string, beforeId: string | undefined
resizeResizes the map according to the dimensions of its container element-
setCenterSets the center point of the mapcenterValue: number[] — longitude/latitude array
jumpToChanges the center point, zoom level, bearing, and pitch without animation. The map will retain the current values for any options not specifiedoptions: object{center, zoom, bearing, pitch}
easeToChanges the center point, zoom level, bearing, and pitch to new values using smooth animation. The map will retain the current values for any options not specifiedoptions: object{center, zoom, bearing, pitch, duration = 1000, easing, offset} => promise
flyToMoves the map to a target location following a flight curveoptions: object{center, zoom, bearing, pitch, duration, easing, offset, animate, curve=1.42, speed=1.2, maxDuration} => promise
stopStops all map panning/flying animations-
cameraForBoundsCalculates and returns the corresponding camera parameters based on the target bounding boxbounds: number[] — The bounding box, with southwest and northeast points as its values, for example:[[-73.9876, 40.7661], [-73.9397, 40.8002]], options: object{padding,offset=[0,0]}
fitBoundsPans and zooms the map to fit the specified geographical bounds within its visible areabounds: number[] — The bounding box, with southwest and northeast points as its values, for example:[[-73.9876, 40.7661], [-73.9397, 40.8002]], options: object{padding,linear=false,offset=[0,0]}
projectReturns a Point representing the pixel coordinates relative to the map's container, corresponding to the specified geographical locationlnglatLike
reorderLayersReorders the layers. The parameter is an array of layer IDsstring[]