Interactive drawing of polygons on the map. Beta version
Please, click on β button.
yarn add @dev-event/react-native-maps-draw
# or
npm install @dev-event/react-native-maps-draw
Also, you need to install react-native-gesture-handler & react-native-svg, and follow theirs installation instructions.
- π I love React Native
Big love and gratitude to all people who are working on React Native, Expo and React Native Navigation!
For more complete example open App.tsx
import React, { useState, useCallback, useRef } from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';
import MapView, {
ILocationProps,
IDrawResult,
TouchPoint,
Marker
} from 'react-native-maps-draw';
const App: React.FC = () => {
const mapRef = useRef<MapView>(null);
const initialPolygon = useRef({
polygons: [],
distance: 0,
lastLatLng: undefined,
initialLatLng: undefined,
centerLatLng: undefined,
});
const [modePolygon, setPolygonCreated] = useState<boolean>(false);
const [isActiveDraw, setDrawMode] = useState<boolean>(false);
const [isReady, setIsReady] = useState<boolean>(false);
const [points, setPoints] = useState<TouchPoint[]>([]);
const [polygon, setPolygon] = useState<IDrawResult>(initialPolygon.current);
const handleMapReady = useCallback(() => mapRef.current && setIsReady(true), []);
const handleRemovePolygon = useCallback(() => {
setPolygon(initialPolygon.current);
setPolygonCreated(false);
}, []);
const handleClear = useCallback(() => {
setPolygon(initialPolygon.current);
setPolygonCreated(false);
setPoints([]);
}, []);
const handleIsDraw = useCallback(() => {
if (!mapRef.current) return;
setDrawMode((prevMode) => !prevMode);
}, [handleClear, isActiveDraw]);
const handleCanvasEndDraw = useCallback((locations) => {
zoomCenterPolygon(locations.centerLatLng).then(() => {
setPolygon(locations);
setPolygonCreated(true);
});
setDrawMode((prevMode) => !prevMode);
}, []);
const zoomCenterPolygon = async (center: ILocationProps) => {
if (!mapRef.current) return;
const camera = await mapRef.current.getCamera();
if (Platform.OS === 'ios') {
mapRef.current.animateCamera({
center: center,
});
}
if (Platform.OS === 'android') {}
};
const hasMarkerClose = polygon.centerLatLng && (
<Marker onPress={handleRemovePolygon} coordinate={polygon.centerLatLng}>
<MarkerLocation />
</Marker>
);
const handlePolygon = useCallback(
(item, index) => <AnimatedPolygon key={index} coordinates={polygon.polygons} />,
[polygon.polygons]
);
return (
<View style={styles.container}>
<MapView
ref={mapRef}
style={{ flex: 1 }}
points={points}
widthLine={3}
onEndDraw={handleCanvasEndDraw}
isDrawMode={isActiveDraw}
onMapReady={handleMapReady}
onStartDraw={handleClear}
createdPolygon={modePolygon}
onChangePoints={setPoints}
backgroundCanvas={'rgba(0, 0, 0, 0.0)'}
>
{isReady && modePolygon && polygon.polygons && polygon.polygons.length > 0 && (
<>
{hasMarkerClose}
{polygon.polygons.map(handlePolygon)}
</>
)}
</MapView>
<TouchableOpacity style={styles.button} onPress={handleIsDraw}>
{isActiveDraw ? (
<Text style={styles.title}>ON</Text>
) : (
<Text style={styles.title}>OFF</Text>
)}
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
button: {
top: '10%',
right: '10%',
position: 'absolute',
backgroundColor: 'tomato',
padding: 16,
zIndex: 4,
borderRadius: 18,
},
title: {
color: '#FFFFFF',
fontSize: 12,
},
});
name | description | required | type | default |
---|---|---|---|---|
points |
An array of x, y coordinates for the drawing of the polygon. | YES | TouchPoint[] |
[] |
unitDistance |
Distance unit | NO | Units |
'm' |
colorLine |
Drawing line color | NO | string | '#791679' |
widthLine |
Drawing line width | NO | number | 3 |
onEndDraw |
Callback is called after drawing is complete | NO | (item: IDrawResult) => void | |
isDrawMode |
Draw mode enabled / disabled | NO | YES | boolean |
renderPath |
Custom canvas for drawing | NO | (path: string) => JSX.Element | |
onStartDraw |
Callback is called when drawing starts | NO | () => void | |
createdPolygon |
Polygon rendering modifier | YES | boolean | true |
onChangePoints |
Callback returns x, y touches | YES | (points: TouchPoint[]) => void | |
fillColorCanvas |
Canvas background | NO | string | 'rgba(0,0,0,0.0)' |
backgroundCanvas |
The background of the View element overlapping the map (zIndex: 1) | NO | string | rgba(0,0,0,0.10) |
Checkout the example here.
- React Native Maps - is a component system for maps that ships with platform-native code that needs to be compiled together with React Native.
- React Native Svg - provides SVG support to React Native on iOS and Android, and a compatibility layer for the web.
Pull requests are always welcome! Feel free to open a new GitHub issue for any changes that can be made.
Reach out to me at one of the following places!
- E-mail effectwaater@gmail.com
- Medium at https://medium.com/@effectwaaters
- Instagram at https://www.instagram.com/dev_event/