map3d — real-time 3D mapping for React: photorealistic globe, DOM markers, a Figma-style drawing editor, and live data.
map3d — cartographie 3D temps réel pour React : globe photoréaliste, markers DOM, éditeur de dessin, données temps réel.
Live demo ↗ · Documentation 🇫🇷 · Documentation 🇬🇧 · Plugins ↗
An imperative Three.js engine driven declaratively by React. MapEngine owns the truth (camera, tiles, layers); React mounts it and stays out of the frame loop — so you get 60 fps on modest laptops without fighting re-renders.
- 🌐 Photorealistic 3D → flat 2D, one library. Google Photorealistic 3D Tiles (via Cesium Ion) with an ellipsoid-globe fallback when no token is set.
- 🧩 Bring your own tiles. The 2D basemap runs from Google or your self-hosted XYZ server — no key, no quota — switched by configuration alone.
- 📍 DOM/CSS markers & clusters with native
:hover, accessibility and animations; pooled nodes,translate3din a single write pass. Stable identity → a moving agent glides instead of being recreated. - ✏️ Full drawing editor, Figma-style: marquee/lasso select, resize & rotate handles, per-tool styles, undo/redo, GeoJSON in/out.
- 🛰️ Live, viewport-driven data: bbox refetch on move + real-time updates.
- 🧭 Coordinate graticule, tag relations, unified search, lens, pedestrian mode, MIL-STD-2525D symbology.
- 🎨 Typed light/dark theme (
prefers-reduced-motionhonoured) and 100 % translatable — no hard-coded string or value anywhere.
npm i @pasquelin/map3d three react react-domthree and react/react-dom 19 are peer dependencies. The MIL-STD symbology SDK (@armyc2.c5isr.renderer/mil-sym-ts-web, ~9 MB) is external to the package: a declared dependency installed alongside it, never inside the library's dist/, loaded on demand through import() the first time a symbol is drawn — it never enters your initial bundle.
A full map with clustered markers in a dozen lines:
import { Map, markersLayer, type MarkerData } from '@pasquelin/map3d'
type Alert = { title: string }
const alerts: MarkerData<Alert>[] = [
{ id: 1, type: 'critical', position: { lat: 48.8566, lng: 2.3522 }, title: 'Intrusion', data: { title: 'Intrusion' } },
{ id: 2, type: 'info', position: { lat: 48.8606, lng: 2.3376 }, title: 'Patrol', data: { title: 'Patrol' } },
]
export function App() {
return (
<div style={{ height: '100vh' }}>
<Map
cesiumIonToken={import.meta.env.VITE_CESIUM_ION_TOKEN} // optional — omit for the globe fallback
center={{ lat: 48.8566, lng: 2.3522 }}
zoom={13}
layers={[markersLayer<Alert>({ points: alerts, cluster: { enabled: true } })]}
/>
</div>
)
}That's it — the toolbar, navigation controls, clustering, search and coordinate grid are all mounted inside <Map> and driven by config; you only add your data.
| 🇫🇷 Français | 🇬🇧 English | |
|---|---|---|
| Guide + index | docs/fr/ | docs/en/ |
| Markers | MARKERS.md | MARKERS.md |
| Zones & shapes | ZONES.md | ZONES.md |
| Drawing | DRAWING.md | DRAWING.md |
| Symbols (MIL-STD) | SYMBOLS.md | SYMBOLS.md |
| Relations | RELATIONS.md | RELATIONS.md |
| Lens | LENS.md | LENS.md |
| Search | SEARCH.md | SEARCH.md |
| Catalog | CATALOG.md | CATALOG.md |
| Camera | CAMERA.md | CAMERA.md |
| Tiles | TILES.md | TILES.md |
| Buildings | BUILDINGS.md | BUILDINGS.md |
| Pedestrian mode | PEDESTRIAN.md | PEDESTRIAN.md |
| Coordinate grid | GRATICULE.md | GRATICULE.md |
| Templates | TEMPLATES.md | TEMPLATES.md |
| Preferences | PREFERENCES.md | PREFERENCES.md |
| Plugins | PLUGINS.md | PLUGINS.md |
| Data | DATA.md | DATA.md |
| Hooks | HOOKS.md | HOOKS.md |
| Engine (no React) | ENGINE.md | ENGINE.md |
MapConfig |
CONFIG.md | CONFIG.md |
MapTheme |
THEME.md | THEME.md |
MapLabels |
LABELS.md | LABELS.md |
| Props | PROPS.md | PROPS.md |
Language folders are named after their ISO 639-1 code and hold identical file names — see docs/README.md to add one.
Optional plugins live in a separate repository: github.com/pasquelin/plugingsMap3D ↗
- GeoPF — French IGN Géoplateforme basemaps & data
- Windy — animated wind/weather overlay
- Plan-3D — indoor / floor-plan overlays
Write your own with the plugin API — start from plugin-template.
The React example runs in the browser at pasquelin.github.io/map3D — published from main on every push, without a Cesium Ion token (photorealistic 3D tiles are off there).
To run it locally, with your own token:
pnpm install
cp examples/react/.env.example examples/react/.env # set VITE_CESIUM_ION_TOKEN (optional)
pnpm dev:exampleReproduces an operator dashboard: 3D map, severity-clustered alerts refetched on move, animated agents with camera follow, zones, drawing, light/dark toggle, an alternative neon theme, and the fallback globe.
The official plugins (GeoPF, Windy, Plan-3D) are optional: the example picks them up when plugingsMap3D is cloned next to this repository (../plugingsMap3D, with its own pnpm install), and runs identically without it. Details in examples/react/README.md.
pnpm build # ESM + CJS + types → dist/
pnpm typecheck # tsc --noEmit (strict)
pnpm test # vitestPolyForm Noncommercial 1.0.0 — free for any noncommercial use (personal, research, nonprofit, education, government).
Commercial use requires a separate license from Alban Pasquelin, the copyright holder — get in touch on LinkedIn.




