1.4.0 โข Published 6 months ago
@robbyawaldi/react-mapbox v1.4.0
@robbyawaldi/react-mapbox
A lightweight and composable React wrapper for Mapbox GL JS using declarative components.
๐ฆ Installation
Install via npm:
npm install @robbyawaldi/react-mapboxYou also need to install its peer dependencies:
npm install mapbox-gl @mapbox/mapbox-gl-draw @turf/turfThen import the required Mapbox CSS styles in your entry file:
import 'mapbox-gl/dist/mapbox-gl.css';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';๐ Basic Usage
Hereโs a minimal example of how to use it in a React component:
import React, { useState } from 'react';
import {
MapContainer,
Geojson,
Layer,
FitBounds,
Center,
Search,
Draw,
} from '@robbyawaldi/react-mapbox';
import * as turf from "@turf/turf";
const App = () => {
const [search, setSearch] = useState("");
const [draws, setDraws] = useState<GeoJSON.FeatureCollection>({
type: "FeatureCollection",
features: [],
});
const handleDraw = useCallback((draw: any) => {
const data = draw.getAll();
const area = turf.area(data);
const rounded_area = Math.round(area * 100) / 100;
setDraws({
type: "FeatureCollection",
features: [],
});
if (rounded_area > 25_000_000) {
alert("out of max area");
} else {
setDraws(data);
}
}, []);
const geojsonData = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: { name: "Location A" },
geometry: {
type: "Point",
coordinates: [106.8272, -6.1751],
},
},
],
};
const layers = useMemo<LayerProps["layers"]>(() => {
return [
{
id: "point-layer",
type: "circle",
paint: {
"circle-radius": 6,
"circle-color": "#007cbf",
},
getMapInstance(map, layerId) {
const popup = new mapboxgl.Popup({ closeButton: false });
map.on("click", layerId, () => {
popup
.setLngLat([106.83173906777137, -6.193283376086626])
.setHTML("<h1>test</h1>")
.addTo(map);
});
map.on("mousemove", layerId, (e) => {
const prevLonglat = popup.getLngLat();
const properties = e.features?.[0].properties;
let longlat = e.lngLat;
if (properties && "longitude" in properties && "latitude") {
longlat = {
lat: properties["latitude"],
lng: properties["longitude"],
} as any;
}
if (
prevLonglat?.lng === longlat.lng &&
prevLonglat?.lat === longlat.lat
)
return;
popup.remove();
popup.setLngLat(longlat).setHTML("<h1>test</h1>").addTo(map);
});
},
},
];
}, []);
return (
<MapContainer
accessToken="YOUR_MAPBOX_TOKEN"
height={400}
mapOption={{
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
center: [106.83173906777137, -6.193283376086626],
zoom: 12,
}}
>
<Geojson id="geo-source" source={geojsonData}>
<Layer layers={layers}/>
</Geojson>
<Geojson id="draw" source={draws}>
<Layer layers={[
{
id: "fill-draw-layer",
type: "fill",
paint: {
"fill-color": "#3BB2D0",
"fill-opacity": 0.3,
},
}
]} />
</Geojson>
<Center center={[106.8272, -6.1751]} zoomLevel={12} />
<FitBounds
bounds={[
106.8272,
-6.1933,
106.8317,
-6.1751,
]}
/>
<Search
keyword={search}
onSearch={(features: any[]) => {
console.log(features)
}}
/>
<Draw onDraw={handleDraw} controls={{ polygon: true, trash: true }} />
</MapContainer>
);
};
export default App;๐ Available Components
| Component | Description |
|---|---|
MapContainer | Root component that initializes the map and provides context. |
Geojson | Provides and shares GeoJSON data via React Context. |
Layer | Adds map layers declaratively, supports images and clustering. |
Center | Sets the map center and zoom level declaratively. |
FitBounds | Automatically fits the map view to the given bounds. |
Search | Performs geocoding via Mapbox Places API using a keyword. |
Draw | Adds interactive drawing tools (polygon, trash). |
useSync | React hook to synchronize multiple mapsโ position and zoom. |
๐ Utility Functions
| Function | Description |
|---|---|
dataParser | Merges external data into a GeoJSON FeatureCollection using a mapping key and optional custom property builder. |