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

Example Source Code
tsx
import React, { useRef, useState } from 'react'
import ReactDOM from 'react-dom'
import { MbMap, MbWmtsLayer } from '@mapbox-react/core'

const App = () => {
  const [mapCenter] = useState([116.3466, 39.8704])
  const [zoom, setZoom] = useState(8)
  const [pitch, setPitch] = useState(0)
  const mapInst = useRef<any>()
  const [mousePosition, setMousePosition] = useState('')

  const easeToRandomPos = () => {
    mapInst.current
      ?.easeTo({
        center: [
          mapCenter[0] + getRandomArbitrary(-1, 1),
          mapCenter[1] + getRandomArbitrary(-1, 1),
        ],
        duration: 2000,
      })
      .then(() => {
        // callback after over
      })
  }
  const flyToRandomPos = () => {
    mapInst.current
      ?.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
  }

  const mouseMoveHandler = (movement) => {
    setMousePosition(movement.coordinates)
  }

  return (
    <div className="map-wrapper">
      <MbMap
        ref={mapInst}
        center={mapCenter}
        zoom={zoom}
        pitch={pitch}
        crs="EPSG:3857"
        extendProps={{
          accessToken:
            'pk.eyJ1IjoiYml0ampqIiwiYSI6ImNtMnNubnlyNTFvNnoycHB5M2M2ZjVpeHEifQ.kk7T4f-CuUA_K6AuPwbvMg',
        }}
        onMouseMove={mouseMoveHandler}
        onZoomChange={(z) => setZoom(z)}
        onPitchChange={(p) => setPitch(p)}
      >
        <div style={{ position: 'absolute', top: '10px', left: '10px' }}>
          <button className="primary mr10" onClick={easeToRandomPos}>
            ease to some position
          </button>
          <button className="primary" onClick={flyToRandomPos}>
            fly to some position
          </button>
        </div>
        <MbWmtsLayer
          url="https://t{s}.tianditu.gov.cn/img_w/wmts?tk=b8ed92ff9b64aebcb0110acca15e478f"
          layerName="img"
          layerStyle="default"
          tileMatrixSetID="w"
          subdomains="01234567"
          maxzoom={18}
        />
      </MbMap>
      <div
        style={{
          position: 'absolute',
          bottom: '0px',
          right: '0px',
          backgroundColor: 'white',
          padding: '10px',
        }}
      >
        <p className="text-muted">
          center:{`${mapCenter}`} zoom:{zoom}
        </p>
        <p className="text-muted">pitch:{`${pitch}`}</p>
        <p className="text-muted">mouse position:{`${mousePosition}`}</p>
      </div>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector('#root'))

Layer Reordering

Example Source Code
tsx
import React, { useState, useRef } from 'react'
import ReactDOM from 'react-dom'
import { MbMap, MbTiandituLayer, MbImageLoader, MbImageFrameLoader, MbSymbolLayer, MbBufferEllipseLayer, MbBufferPolygonLayer } from '@mapbox-react/core'

const App = () => {
  const [mapCenter] = useState([116.3466, 39.8704])
  const [zoom, setZoom] = useState(10)

  const mapInst = useRef<any>()
  const symbolDataSource = [
    {
      coordinates: [116.45346681596038, 39.90085772830014],
      properties: {
        icon: 'event',
      },
    },
    {
      coordinates: [...mapCenter],
      properties: {
        icon: 'event',
      },
    },
  ]
  const symbolDataSource2 = [
    {
      coordinates: [116.46346681596, 39.90085772830014],
      properties: {
        icon: 'event2',
      },
    },
    {
      coordinates: [...mapCenter],
      properties: {
        icon: 'event2',
      },
    },
  ]
  const symbolDataSource3 = [
    {
      coordinates: [116.47346681596038, 39.94085772830014],
      properties: {
        icon: 'event3',
        iconSize: 0.1,
      },
    },
    {
      coordinates: [...mapCenter],
      properties: {
        icon: 'event3',
        iconSize: 0.1,
      },
    },
  ]
  const polygon = [
    [116.17381, 39.92155464],
    [116.25105956968257, 40.02398993628292],
    [116.31591012802686, 39.96769599504311],
  ]
  const images = [
    {
      name: 'event',
      type: 'link',
      url: `https://mapbox-web.github.io/mapbox-react/images/common_toget.png`,
    },
    {
      name: 'event2',
      type: 'link',
      url: `https://mapbox-web.github.io/mapbox-react/images/eme_team_soc_toget.png`,
    },
  ]
  const images2 = [
    {
      name: 'event3',
      dir: 'v' as const,
      steps: 3,
      duration: 300,
      url: `https://mapbox-web.github.io/mapbox-react/images/v-steps.png`,
    },
  ]

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

  return (
    <div className="map-wrapper">
      <MbMap
        ref={mapInst}
        center={mapCenter}
        zoom={zoom}
      >
        <div style={{ position: 'absolute', top: '10px', left: '10px' }}>
          <button onClick={() => reorder(['buffer2', 's3', 'buffer1', 's2', 's1'])}>Order:buffer2, s3, buffer1, s2, s1(top)</button>
          <button onClick={() => reorder(['s2', 's3', 's1', 'buffer2', 'buffer1'])}>Order:s2, s3, s1, buffer2, buffer1(top)</button>
        </div>
        <MbTiandituLayer types={['vec', 'cva']} />
        <MbImageLoader images={images} />
        <MbImageFrameLoader images={images2} />
        <MbSymbolLayer
          id="s1"
          data={symbolDataSource}
          textField="label"
          iconImageField="icon"
          iconSize={0.5}
          textOffset={[0, -1]}
          iconAllowOverlap={true}
          textAllowOverlap={true}
        />
        <MbBufferEllipseLayer
          id="buffer1"
          center={mapCenter}
          xSemiAxis={10}
          ySemiAxis={5}
          angle={0}
        />
        <MbSymbolLayer
          id="s2"
          data={symbolDataSource2}
          textField="label"
          iconImageField="icon"
          iconSize={0.5}
          textOffset={[0, -1]}
          cluster={true}
          spiderify={true}
          clusterMaxZoom={18}
          iconAllowOverlap={true}
          textAllowOverlap={true}
        />
        <MbSymbolLayer
          id="s3"
          data={symbolDataSource3}
          textField="label"
          iconImageField="icon"
          iconSize={0.5}
          textOffset={[0, -1]}
          iconAllowOverlap={true}
          textAllowOverlap={true}
        />
        <MbBufferPolygonLayer
          id="buffer2"
          polygon={polygon}
          radius={7}
          center={mapCenter}
        />
      </MbMap>
    </div>
  );
}

ReactDOM.render(<App />,
  document.getElementById("root"))

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 onCreated event of MbMap.

  • If your component can be placed inside the MbMap component, you can use the MapContext context provided by the component library to get the map instance.
demo3.tsx
tsx
import { MbMap } from '@mapbox-react/core'
import Instance1 from './instance1'

function Demo3() {
  return (
    <div style={{ height: '400px' }} className="vw-full vh-full">
      <MbMap>
        <Instance1 />
      </MbMap>
    </div>
  )
}

export default Demo3
instance1.tsx
tsx
import { useContext } from 'react'
import { MapContext } from '@mapbox-react/core'

function Instance1() {
  const mapContext = useContext(MapContext)

  console.log(mapContext.mapInstance, mapContext.mapboxInstance)
}

export default Instance1
  • 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 onCreated 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-react/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 }
tsx
import { MbMap } from '@mapbox-react/core'
import { useMap } from './use-map'

function App() {
  const { onCreated } = useMap()

  return <MbMap onCreated={onCreated}> ... </MbMap>
}

export default App

In the place where you need to use it:

tsx
import { useMap } from './use-map'

const { getMapbox } = useMap()

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-react/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 }
tsx
// instance.tsx
import { useEffect } from 'react'
import { useMap } from './use-map'
import { waitingForMap } from './map-deferred'

function Instance() {
  const { getMapbox } = useMap()

  useEffect(() => {
    const operateMap = async() => {
      await waitingForMap()
      // 下面可以使用getMapbox()获取地图实例进行操作了
      console.log('operate', getMapbox())
    }
    operateMap()
  }, [])

  return <></>
}

export default Instance
tsx
import { MbMap } from '@mapbox-react/core'
import { useMap } from './use-map'
import Instance from './instance'

function App() {
  const { onCreated } = useMap()

  return <>
    <MbMap onCreated={onCreated}> ... </MbMap>
    <Instance />
  </>
}

export default App

API

PROPS

NameDescriptionTypeDefault
antialiasWhether to enable antialiasing; disabling it can improve performancebooleantrue
bearingThe 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
centerThe geographic center point of the map, using the order of longitude, latitudenumber[][116.38745, 39.91266]
mapStyleMap 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-
maxBoundsAfter 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
pitchThe initial pitch of the mapnumber0
zoomThe 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-
extendPropsExtended properties. See the Mapbox documentationIndexAny{}
childrenchildren nodesany-

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: bearingcenterpitchzoom, 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

名称描述参数
onCreatedEvent triggered when the map is initializedmap: MapboxInstance
onZoomChangeEvent triggered when the map's zoom level changesnumber
onCenterChangeEvent triggered when the map's center changesnumber[]
onBearingChangeEvent triggered when the map's bearing changesnumber
onPitchChangeEvent triggered when the map's pitch changesnumber
onClickMouse click event. Triggered on every clickobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
onDoubleClickMouse double-click eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
onSingleClickMouse single-click eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
onMouseMoveMouse move eventobject — Contains screen coordinates pixel, latitude/longitude coordinate, and originalEvent
onMouseOutMouse leaves the map areaMapMouseEvent & EventData

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