react-three-map
is a bridge to use react-three-fiber
inside react-map-gl
.
Until now you had:
imperative | declarative (react) |
---|---|
Maplibre/Mapbox | react-map-gl |
THREE.js | react-three-fiber |
Now with react-three-map
, you can use them together ๐คโญ๐ค.
npm install react-three-map
Check out our examples here (powered by Ladle).
Let's build the same react-three-fiber basic example, but now it can be inside a map. (live demo). |
![]() |
- Import
Canvas
fromreact-three-map
instead of@react-three/fiber
. - Give it a latitude and longitude so it knows where to position the scene in the map.
- Everything else should work just as usual.
import "maplibre-gl/dist/maplibre-gl.css"
import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { useFrame } from "@react-three/fiber"
import { useRef, useState } from "react"
import Map from "react-map-gl/maplibre"
import { Canvas } from "react-three-map/maplibre"
// import { Canvas } from "react-three-map" // if you are using MapBox
function BasicExample() {
return <Map
antialias
initialViewState={{
latitude: 51,
longitude: 0,
zoom: 13,
pitch: 60
}}
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
>
<Canvas latitude={51} longitude={0}>
<hemisphereLight
args={["#ffffff", "#60666C"]}
position={[1, 4.5, 3]}
/>
<object3D scale={500}>
<Box position={[-1.2, 1, 0]} />
<Box position={[1.2, 1, 0]} />
</object3D>
</Canvas>
</Map>
}
Look how complex is to add just one ThreeJS object to a map.
Look how complex is to create your custom root for R3F.
You can now replace all that complexity and hundreds of lines of code with the <Canvas>
component exported by react-three-map
, which includes a tone of extra features and seamless integration, supporting pointer events, raycasting, and much more, all out of the box.
Same as in @react-three/fiber
, the <Canvas>
object is where you start to define your React Three Fiber Scene.
import "maplibre-gl/dist/maplibre-gl.css"
import Map from "react-map-gl/maplibre"
import { Canvas } from 'react-three-map/maplibre'
// import { Canvas } from "react-three-map" // if you are using MapBox
const App = () => (
<Map
initialViewState={{ latitude: 51, longitude: 0, zoom: 13 }}
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" >
<Canvas latitude={51} longitude={0}>
<pointLight position={[10, 10, 10]} />
<mesh>
<sphereGeometry />
<meshStandardMaterial color="hotpink" />
</mesh>
</Canvas>
</Map>
)
It shares most of the props from R3F <Canvas>
, so you can check them directly in the @react-three/fiber
docs. There are a few important exceptions though, which are mentioned bellow.
Prop | Description | Default |
---|---|---|
latitude | The latitude coordinate where to add the scene. | |
longitude | The longitude coordinate where to add the scene. | |
altitude | The altitude coordinate where to add the scene. | 0 |
frameloop | Render mode: "always" , "demand" . |
"always" |
Because the scene now lives in a map, we leave a lot of the render and camera control to the map, rather than to R3F.
Therefore, the following <Canvas>
props are ignored:
- gl
- camera
- resize
- orthographic
- dpr
This component allows you to have 3D objects at different coordinates.
import { Canvas, Coordinates } from 'react-three-map'
<Canvas latitude={51} longitude={0}>
<Coordinates latitude={50} longitude={0}>
<mesh><sphereGeometry /></mesh>
</Coordinates>
<Coordinates latitude={52} longitude={0}>
<mesh><sphereGeometry /></mesh>
</Coordinates>
</Canvas>
Props | Description | Default |
---|---|---|
latitude | The latitude coordinate where to add the scene. | |
longitude | The longitude coordinate where to add the scene. | |
altitude | The altitude coordinate where to add the scene. | 0 |
Access the map from inside react-three-map
.
import { useMap } from "react-three-map";
// import { useMap } from "react-three-map/maplibre"; if you use maplibre
const Component = () => {
const map = useMap();
return <>...</>
}