Skip to content

Commit fb8f446

Browse files
committed
Merge branch 'features/draw' into develop
2 parents be9e927 + b96e711 commit fb8f446

35 files changed

+813
-55
lines changed

.editorconfig

Lines changed: 0 additions & 15 deletions
This file was deleted.

.prettierrc.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "all",
4+
"singleQuote": true,
5+
"printWidth": 90,
6+
"tabWidth": 4
7+
}

.yarnrc

Lines changed: 0 additions & 3 deletions
This file was deleted.

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 Aliaksei Petrusevich
3+
Copyright (c) 2020 Aliaksei Petrusevich
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,107 @@
1-
# react-native-maps-draw
1+
<div align="center">
2+
<img src="./draw.gif" height="500" title="React Native Maps Draw Polygon" alt="Accordion Animated" style="box-shadow: 0 20px 30px 3px rgba(9, 9, 16, 0.2);">
3+
</div>
4+
5+
<br>
6+
<br>
7+
8+
<h1 align="center">React Native Maps Draw (Polygon)</h1>
9+
<p align="center">Performance oriented React Native Accordion 60 FPS. A simple component of a common use case of collapsible - a visible title with a collapsible view beneath it.</p>
10+
<h6 align="center">Made with ❤️ by developer for developers</h6>
11+
12+
<br>
13+
<p align="center">
14+
<img src="http://img.shields.io/travis/badges/badgerbadgerbadger.svg?style=flat-square" alt="build"/>
15+
<img src="https://img.shields.io/github/issues/dev-event/react-native-accordion" alt="build"/>
16+
<img src="https://img.shields.io/bitbucket/pr-raw/dev-event/react-native-accordion" alt="build"/>
17+
<img src="http://img.shields.io/:license-mit-blue.svg?style=flat-square" alt="build"/>
18+
</p>
19+
20+
21+
22+
## Thanks
23+
<p>Please, click on ⭐ button.</p>
24+
25+
# Documentation & Examples
26+
27+
- [Installation](#installation)
28+
- [Motivation](#motivation)
29+
- [Usage](#usage)
30+
- [Props](#props)
31+
- [Example](#example)
32+
- [What's inside](#whats-inside)
33+
- [Contributing](#contributing)
34+
- [Author](#author)
35+
- [License](#license)
36+
37+
## Installation
38+
39+
```bash
40+
yarn add react-native-maps-draw
41+
# or
42+
npm install react-native-maps-draw
43+
```
44+
> Also, you need to install [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler) & [react-native-svg](https://github.com/react-native-community/react-native-svg), and follow theirs installation instructions.
45+
46+
## 🦥 Motivation
47+
- 💚 I love [React Native](https://reactnative.dev/)
48+
49+
50+
Big love and gratitude to all people who are working on React Native, Expo and React Native Navigation!
51+
52+
## Usage
53+
54+
For more complete example open [App.tsx](https://github.com/dev-event/react-native-accordion)
55+
56+
```tsx
57+
58+
```
59+
60+
61+
62+
63+
## Props
64+
65+
| name | description | required | type | default |
66+
| -------------------- | --------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------| -----------------|
67+
| `points` | An array of x, y coordinates for the drawing of the polygon. | YES | [`TouchPoint[]`](https://github.com/dev-event/react-native-maps-draw/blob/features/draw/src/types/index.ts) | [] |
68+
| `unitDistance` | Distance unit | NO | [`TouchPoint[]`](https://github.com/dev-event/react-native-maps-draw/blob/features/draw/src/maps/types.d.ts)| 'm' |
69+
| `colorLine` | Drawing line color | NO | string | '#791679' |
70+
| `widthLine` | Drawing line width | NO | number | 3 |
71+
| `onEndDraw` | Callback is called after drawing is complete | NO | (item: IDrawResult) => void | |
72+
| `isDrawMode` | Draw mode enabled / disabled | NO | YES | boolean | false |
73+
| `renderPath` | Custom canvas for drawing | NO | (path: string) => JSX.Element | |
74+
| `onStartDraw` | Callback is called when drawing starts | NO | () => void | |
75+
| `createdPolygon` | Polygon rendering modifier | YES | boolean | true |
76+
| `onChangePoints` | Callback returns x, y touches | YES | (points: TouchPoint[]) => void | |
77+
| `fillColorCanvas` | Canvas background | NO | string | 'rgba(0,0,0,0.0)'|
78+
| `backgroundCanvas` | The background of the View element overlapping the map (zIndex: 1) | NO | string | rgba(0,0,0,0.10) |
79+
80+
## 🎉 Example
81+
82+
Checkout the example [here](https://github.com/dev-event/react-native-accordion).
83+
84+
85+
## 📖 What's inside
86+
- [React Native Maps](https://github.com/wix/react-native-navigation) - is a component system for maps that ships with platform-native code that needs to be compiled together with React Native.
87+
- [React Native Svg](https://github.com/react-native-svg/react-native-svg) - provides SVG support to React Native on iOS and Android, and a compatibility layer for the web.
88+
89+
90+
## ✌️ Contributing
91+
92+
Pull requests are always welcome! Feel free to open a new GitHub issue for any changes that can be made.
93+
94+
## Author
95+
96+
Reach out to me at one of the following places!
97+
98+
- E-mail <a href="#" target="_blank">effectwaater@gmail.com</a>
99+
- Medium at <a href="https://medium.com/@effectwaaters" target="_blank">https://medium.com/@effectwaaters </a>
100+
- Instagram at <a href="https://www.instagram.com/dev_event/" target="_blank">https://www.instagram.com/dev_event/ </a>
101+
102+
103+
## License
104+
105+
[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org)
106+
107+
- **[MIT license](http://opensource.org/licenses/mit-license.php)**

babel.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
module.exports = {
22
presets: ['module:metro-react-native-babel-preset'],
3+
plugins: ['react-native-reanimated/plugin'],
34
};

draw.gif

6.05 MB
Loading

example/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
"devDependencies": {
2424
"@babel/core": "~7.12.10",
2525
"@babel/runtime": "^7.9.6",
26+
"@types/react": "~16.9.35",
27+
"@types/react-native": "~0.63.2",
2628
"babel-plugin-module-resolver": "^4.0.0",
2729
"babel-preset-expo": "8.3.0",
28-
"expo-cli": "^4.0.13"
30+
"expo-cli": "^4.0.13",
31+
"typescript": "~4.0.0"
2932
}
3033
}

example/src/App.tsx

Lines changed: 158 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,175 @@
1-
import * as React from 'react';
2-
3-
import { StyleSheet, View, Text } from 'react-native';
4-
import MapsDraw from 'react-native-maps-draw';
1+
import React, { useState, useCallback, useRef } from 'react';
2+
import { StyleSheet, View, TouchableOpacity, Platform, Text } from 'react-native';
3+
import MapView, { ILocationProps, IDrawResult, TouchPoint, Marker } from '../../src';
4+
import { MarkerLocation } from './assets';
5+
import AnimatedPolygon from './components/polygon';
56

67
export default function App() {
7-
const [result, setResult] = React.useState<number | undefined>();
8+
const mapRef = useRef<MapView>(null);
9+
10+
const initialPolygon = useRef({
11+
polygons: [],
12+
distance: 0,
13+
lastLatLng: undefined,
14+
initialLatLng: undefined,
15+
centerLatLng: undefined,
16+
});
17+
18+
const [modePolygon, setPolygonCreated] = useState<boolean>(false);
19+
20+
const [isActiveDraw, setDrawMode] = useState<boolean>(false);
21+
const [isReady, setIsReady] = useState<boolean>(false);
22+
const [points, setPoints] = useState<TouchPoint[]>([]);
23+
24+
const [polygon, setPolygon] = useState<IDrawResult>(initialPolygon.current);
25+
26+
const handleMapReady = useCallback(() => mapRef.current && setIsReady(true), []);
827

9-
React.useEffect(() => {
10-
MapsDraw.multiply(3, 7).then(setResult);
28+
const handleRemovePolygon = useCallback(() => {
29+
setPolygon(initialPolygon.current);
30+
setPolygonCreated(false);
1131
}, []);
1232

33+
const handleClear = useCallback(() => {
34+
setPolygon(initialPolygon.current);
35+
setPolygonCreated(false);
36+
setPoints([]);
37+
}, []);
38+
39+
const handleIsDraw = useCallback(() => {
40+
if (!mapRef.current) return;
41+
if (!isActiveDraw) {
42+
zoomOut().then(handleClear);
43+
}
44+
setDrawMode((prevMode) => !prevMode);
45+
}, [handleClear, isActiveDraw]);
46+
47+
const handleCanvasEndDraw = useCallback((locations) => {
48+
zoomCenterPolygon(locations.centerLatLng).then(() => {
49+
setPolygon(locations);
50+
setPolygonCreated(true);
51+
});
52+
setDrawMode((prevMode) => !prevMode);
53+
}, []);
54+
55+
const zoomCenterPolygon = async (center: ILocationProps) => {
56+
if (!mapRef.current) return;
57+
const camera = await mapRef.current.getCamera();
58+
if (Platform.OS === 'ios') {
59+
mapRef.current.animateCamera({
60+
center: center,
61+
// altitude: camera.altitude / 2,
62+
});
63+
}
64+
if (Platform.OS === 'android') {
65+
// mapRef.current.animateCamera({ center, zoom: camera.zoom + 1 });
66+
}
67+
};
68+
69+
const zoomOut = async () => {
70+
if (!mapRef.current) return false;
71+
72+
const camera = await mapRef.current.getCamera();
73+
if (Platform.OS === 'ios') {
74+
mapRef.current.animateCamera({ altitude: camera.altitude * 1 });
75+
}
76+
77+
if (Platform.OS === 'android') {
78+
mapRef.current.animateCamera({ zoom: camera.zoom - 1 });
79+
}
80+
};
81+
82+
const hasMarkerClose = polygon.centerLatLng && (
83+
<Marker onPress={handleRemovePolygon} coordinate={polygon.centerLatLng}>
84+
<MarkerLocation />
85+
</Marker>
86+
);
87+
88+
const handlePolygon = useCallback(
89+
(item, index) => <AnimatedPolygon key={index} coordinates={polygon.polygons} />,
90+
[polygon.polygons]
91+
);
92+
93+
const onChangePoints = useCallback((value) => {
94+
setPoints(value);
95+
}, []);
96+
97+
//
98+
// const hasOverlay = useMemo(() => {
99+
// if (renderOverlayPolygon === null) {
100+
// return null;
101+
// }
102+
//
103+
// return renderOverlayPolygon !== undefined
104+
// ? renderOverlayPolygon(path)
105+
// : !!path && (
106+
// <OverlayPolygon
107+
// {...{
108+
// path,
109+
// fillOverlay,
110+
// widthOverlayLine,
111+
// colorWidthOverlayLine,
112+
// backgroundOverlayPolygon,
113+
// }}
114+
// />
115+
// );
116+
// }, [
117+
// path,
118+
// fillOverlay,
119+
// widthOverlayLine,
120+
// renderOverlayPolygon,
121+
// colorWidthOverlayLine,
122+
// backgroundOverlayPolygon,
123+
// ]);
13124
return (
14125
<View style={styles.container}>
15-
<Text>Result: {result}</Text>
126+
<MapView
127+
ref={mapRef}
128+
style={{ flex: 1 }}
129+
points={points}
130+
widthLine={3}
131+
onEndDraw={handleCanvasEndDraw}
132+
isDrawMode={isActiveDraw}
133+
onMapReady={handleMapReady}
134+
onStartDraw={handleClear}
135+
createdPolygon={modePolygon}
136+
onChangePoints={onChangePoints}
137+
backgroundCanvas={'rgba(0, 0, 0, 0.0)'}
138+
>
139+
{isReady && modePolygon && polygon.polygons && polygon.polygons.length > 0 && (
140+
<>
141+
{hasMarkerClose}
142+
{polygon.polygons.map(handlePolygon)}
143+
</>
144+
)}
145+
</MapView>
146+
147+
<TouchableOpacity style={styles.button} onPress={handleIsDraw}>
148+
{isActiveDraw ? (
149+
<Text style={styles.title}>ON</Text>
150+
) : (
151+
<Text style={styles.title}>OFF</Text>
152+
)}
153+
</TouchableOpacity>
16154
</View>
17155
);
18156
}
19157

20158
const styles = StyleSheet.create({
21159
container: {
22160
flex: 1,
23-
alignItems: 'center',
24-
justifyContent: 'center',
25161
},
26-
box: {
27-
width: 60,
28-
height: 60,
29-
marginVertical: 20,
162+
button: {
163+
top: '10%',
164+
right: '10%',
165+
position: 'absolute',
166+
backgroundColor: 'tomato',
167+
padding: 16,
168+
zIndex: 4,
169+
borderRadius: 18,
170+
},
171+
title: {
172+
color: '#FFFFFF',
173+
fontSize: 12,
30174
},
31175
});

example/src/assets/gps-marker.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import { SvgXml } from 'react-native-svg';
3+
4+
const GpsLocation = () => {
5+
const svgMarkup = `
6+
<svg version='1.1' id='Capa_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 477.112 477.112' style='enable-background:new 0 0 477.112 477.112;' xml:space='preserve'>
7+
<linearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='-28.319' y1='557.986' x2='-28.319' y2='618.787' gradientTransform='matrix(8 0 0 -8 465.108 4941)'>
8+
<stop offset='0' style='stop-color:#006DF0'/>
9+
<stop offset='1' style='stop-color:#00E7F0'/>
10+
</linearGradient>
11+
<path style='fill:url(#SVGID_1_);' d='M238.556,0c-92.74,0.106-167.894,75.26-168,168c0,90.056,155.064,292.32,161.664,300.88
12+
l6.336,8.232l6.336-8.232c6.6-8.56,161.664-210.824,161.664-300.88C406.45,75.26,331.296,0.106,238.556,0z M238.556,450.728
13+
c-29.528-39.528-152-207.896-152-282.728c0-83.947,68.053-152,152-152s152,68.053,152,152
14+
C390.556,242.816,268.084,411.2,238.556,450.728z'/>
15+
<linearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='-28.319' y1='558.035' x2='-28.319' y2='618.838' gradientTransform='matrix(8 0 0 -8 465.108 4941)'>
16+
<stop offset='0' style='stop-color:#006DF0'/>
17+
<stop offset='1' style='stop-color:#00E7F0'/>
18+
</linearGradient>
19+
<path style='fill:url(#SVGID_2_);' d='M238.556,112c-30.928,0-56,25.072-56,56s25.072,56,56,56s56-25.072,56-56
20+
C294.521,137.087,269.469,112.035,238.556,112z M238.556,208c-22.091,0-40-17.909-40-40s17.909-40,40-40s40,17.909,40,40
21+
C278.53,190.08,260.636,207.974,238.556,208z'/>
22+
</svg>`;
23+
24+
return <SvgXml xml={svgMarkup} width={36} height={36} />;
25+
};
26+
27+
export default GpsLocation;

0 commit comments

Comments
 (0)