@dev-event/react-native-maps-draw

Interactive drawing of polygons on the map.

Usage no npm install needed!

<script type="module">
  import devEventReactNativeMapsDraw from 'https://cdn.skypack.dev/@dev-event/react-native-maps-draw';
</script>

README

Accordion Animated


React Native Maps Draw (Polygon)

Interactive drawing of polygons on the map. Beta version

Made with ❤️ by developer for developers

build build build build

Thanks

Please, click on ⭐ button.

Documentation & Examples

Installation

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.

🦥 Motivation

Big love and gratitude to all people who are working on React Native, Expo and React Native Navigation!

Usage

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,
  },
});

Props

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)

🎉 Example

Checkout the example here.

📖 What's inside

  • 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.

✌️ Contributing

Pull requests are always welcome! Feel free to open a new GitHub issue for any changes that can be made.

Author

Reach out to me at one of the following places!

License

License