I have been following this documentation for drawing polygon on map. Now I tried to fetch the value for latitude and longitude from API and draw it. For a small amount of value, it is not a problem as I just directly wrote it from using state.
Below are my render function
import React, { Component } from 'react';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
import { Card, Button } from 'react-native-elements';
import { MapView } from 'expo';
import { connect } from 'react-redux';
const window = Dimensions.get('window');
class PolygonPage extends Component {
constructor(props) {
super(props);
this.state = {
polygon: [
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][1][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][1][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][2][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][2][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][3][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][3][0]
}
]
};
}
onButtonPressClose = () => {
this.props.navigation.navigate('Home');
}
render() {
const { polygon } = this.state;
return (
<View style={styles.container}>
<MapView
provider={this.props.provider}
style={styles.map}
zoomEnabled
initialRegion={{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][0],
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
<MapView.Polygon
coordinates={polygon}
fillColor="rgba(0, 200, 0, 0.5)"
strokeColor="rgba(0,0,0,0.5)"
strokeWidth={2}
/>
</MapView>
<View style={stylesContainer.topContainer}>
<Card title="Route Information">
<View>
<Text>Name: {this.props.points.data.name}</Text>
<Text>Description: {this.props.routes.data.description}</Text>
</View>
</Card>
</View>
<View style={stylesContainer.buttonBottomContainer}>
<Button
medium
title="Back"
backgroundColor="#94b8b8"
onPress={this.onButtonPressClose}
/>
</View>
</View>
);
}
}
PolygonPage.propTypes = {
provider: MapView.ProviderPropType,
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
flex: 1,
height: window.height,
width: window.width
}
});
function mapStateToProps({ points }) {
return { points };
}
export default connect(mapStateToProps)(PolygonPage);
This works for me as it rendered a polygon from the point that I got from API.
My API response is in JSON. This is the example
{
"timestamp": 000111,
"verb": "GET",
"object": "route",
"data": {
"description": "describe",
"routeGeoJSON": {
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
122.18919, // this is longitude
4.82948294 // this is latitude
],
[
124.17318,
5.9319319
],
[
101.131191,
2.92492
],
[
106.01010192,
4.492472492
]
]
]
},
"type": "Feature",
"properties": {}
}
]
},
"id": 1,
"routeType": "point",
"name": "Test"
}
}
If the points/coordinates is less than 10, than I might probably input it as what I did in my render function. But what if there is more than 10 points(latitude and longitude)? I could not figure how should I use map
or for
loop function inside this.state = { polygon: [....]}
.
I have searched online and found some example like this and this but failed to grab the understanding of it.
If anyone have any idea or kind enough to share his suggestion or boilerplate here, I am very thankful for that.
Thank you.
I have been following this documentation for drawing polygon on map. Now I tried to fetch the value for latitude and longitude from API and draw it. For a small amount of value, it is not a problem as I just directly wrote it from using state.
Below are my render function
import React, { Component } from 'react';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
import { Card, Button } from 'react-native-elements';
import { MapView } from 'expo';
import { connect } from 'react-redux';
const window = Dimensions.get('window');
class PolygonPage extends Component {
constructor(props) {
super(props);
this.state = {
polygon: [
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][1][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][1][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][2][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][2][0]
},
{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][3][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][3][0]
}
]
};
}
onButtonPressClose = () => {
this.props.navigation.navigate('Home');
}
render() {
const { polygon } = this.state;
return (
<View style={styles.container}>
<MapView
provider={this.props.provider}
style={styles.map}
zoomEnabled
initialRegion={{
latitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][1],
longitude: this.props.points.data.routeGeoJSON.features[0].geometry.coordinates[0][0][0],
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
<MapView.Polygon
coordinates={polygon}
fillColor="rgba(0, 200, 0, 0.5)"
strokeColor="rgba(0,0,0,0.5)"
strokeWidth={2}
/>
</MapView>
<View style={stylesContainer.topContainer}>
<Card title="Route Information">
<View>
<Text>Name: {this.props.points.data.name}</Text>
<Text>Description: {this.props.routes.data.description}</Text>
</View>
</Card>
</View>
<View style={stylesContainer.buttonBottomContainer}>
<Button
medium
title="Back"
backgroundColor="#94b8b8"
onPress={this.onButtonPressClose}
/>
</View>
</View>
);
}
}
PolygonPage.propTypes = {
provider: MapView.ProviderPropType,
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
flex: 1,
height: window.height,
width: window.width
}
});
function mapStateToProps({ points }) {
return { points };
}
export default connect(mapStateToProps)(PolygonPage);
This works for me as it rendered a polygon from the point that I got from API.
My API response is in JSON. This is the example
{
"timestamp": 000111,
"verb": "GET",
"object": "route",
"data": {
"description": "describe",
"routeGeoJSON": {
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
122.18919, // this is longitude
4.82948294 // this is latitude
],
[
124.17318,
5.9319319
],
[
101.131191,
2.92492
],
[
106.01010192,
4.492472492
]
]
]
},
"type": "Feature",
"properties": {}
}
]
},
"id": 1,
"routeType": "point",
"name": "Test"
}
}
If the points/coordinates is less than 10, than I might probably input it as what I did in my render function. But what if there is more than 10 points(latitude and longitude)? I could not figure how should I use map
or for
loop function inside this.state = { polygon: [....]}
.
I have searched online and found some example like this and this but failed to grab the understanding of it.
If anyone have any idea or kind enough to share his suggestion or boilerplate here, I am very thankful for that.
Thank you.
Share Improve this question asked Nov 20, 2017 at 10:16 FangFang 8444 gold badges17 silver badges34 bronze badges 1-
1
Code from the
React Native Map
examples : github./airbnb/react-native-maps/blob/master/example/… , Please have a look at it, this might be helpful. – katwal-dipak Commented Dec 2, 2017 at 17:46
2 Answers
Reset to default 2You have to map
through your response and then transform your coordinates into the type
given in the documentation
type LatLng {
latitude: Number,
longitude: Number,
}
Assuming your API response is saved in apiResponse
, try this.
You access your object with keys
and array Positions and the you map through your coordinates array.
const polygon = apiResponse.data.routeGeoJSON[0].geometry.coordinates[0].map(coordsArr => {
let coords = {
latitude: coordsArr[1],
longitude: coordsArr[0],
}
return coords;
});
The const polygon
is what you give your
<MapView.Polygon
coordinates={polygon} />
Here is the final code:
Just create a file Maps.js and paste code and call it from the navigator
import React, { Component } from 'react'
import {
StyleSheet,
View,
Text,
Dimensions,
TouchableOpacity
} from 'react-native'
import MapView, {
MAP_TYPES,
Polygon,
ProviderPropType,
PROVIDER_GOOGLE
} from 'react-native-maps'
const { width, height } = Dimensions.get('window')
const ASPECT_RATIO = width / height
const LATITUDE = 37.78825
const LONGITUDE = -122.4324
const LATITUDE_DELTA = 0.0922
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO
let id = 0
class Maps extends Component {
constructor(props) {
super(props)
this.state = {
region: {
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
},
polygons: [],
editing: null,
creatingHole: false
}
}
finish() {
const { polygons, editing } = this.state;
this.setState({
polygons: [...polygons, editing],
editing: null,
creatingHole: false,
});
}
clear = () => {
this.setState({
polygons: [],
editing: null,
creatingHole: false
})
}
createHole() {
const { editing, creatingHole } = this.state
if (!creatingHole) {
this.setState({
creatingHole: true,
editing: {
...editing,
holes: [...editing.holes, []]
}
})
} else {
const holes = [...editing.holes]
if (holes[holes.length - 1].length === 0) {
holes.pop()
this.setState({
editing: {
...editing,
holes
}
})
}
this.setState({ creatingHole: false })
}
}
onPress(e) {
console.log(this.state.polygons)
const { editing, creatingHole } = this.state
if (!editing) {
this.setState({
editing: {
id: id++,
coordinates: [e.nativeEvent.coordinate],
holes: []
}
})
} else if (!creatingHole) {
this.setState({
editing: {
...editing,
coordinates: [...editing.coordinates, e.nativeEvent.coordinate]
}
})
} else {
const holes = [...editing.holes]
holes[holes.length - 1] = [
...holes[holes.length - 1],
e.nativeEvent.coordinate
]
this.setState({
editing: {
...editing,
id: id++, // keep incrementing id to trigger display refresh
coordinates: [...editing.coordinates],
holes
}
})
}
}
render() {
const mapOptions = {
scrollEnabled: true
}
if (this.state.editing) {
mapOptions.scrollEnabled = false
mapOptions.onPanDrag = e => this.onPress(e)
}
return (
<View style={styles.container}>
<MapView
provider={PROVIDER_GOOGLE}
style={styles.map}
mapType={MAP_TYPES.SATELLITE}
initialRegion={this.state.region}
onPress={e => this.onPress(e)}
{...mapOptions}
>
{this.state.polygons.map(polygon => (
<Polygon
key={polygon.id}
coordinates={polygon.coordinates}
holes={polygon.holes}
strokeColor="#F00"
fillColor="rgba(255,0,0,0.5)"
strokeWidth={1}
/>
))}
{this.state.editing && (
<Polygon
key={this.state.editing.id}
coordinates={this.state.editing.coordinates}
holes={this.state.editing.holes}
strokeColor="#000"
fillColor="rgba(255,0,0,0.5)"
strokeWidth={1}
/>
)}
</MapView>
<View style={styles.buttonContainer}>
{this.state.editing && (
<TouchableOpacity
onPress={() => this.createHole()}
style={[styles.bubble, styles.button]}
>
<Text>
{this.state.creatingHole ? 'Finish Hole' : 'Create Hole'}
</Text>
</TouchableOpacity>
)}
{this.state.editing && (
<TouchableOpacity
onPress={() => this.finish()}
style={[styles.bubble, styles.button]}
>
<Text>Finish</Text>
</TouchableOpacity>
)}
</View>
<TouchableOpacity
onPress={() => this.clear()}
style={[styles.bubble, styles.button]}
>
<Text>Clear</Text>
</TouchableOpacity>
</View>
)
}
}
Maps.propTypes = {
provider: ProviderPropType
}
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'flex-end',
alignItems: 'center'
},
map: {
...StyleSheet.absoluteFillObject
},
bubble: {
backgroundColor: 'rgba(255,255,255,0.7)',
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 20
},
latlng: {
width: 200,
alignItems: 'stretch'
},
button: {
width: 80,
paddingHorizontal: 12,
alignItems: 'center',
marginHorizontal: 10
},
buttonContainer: {
flexDirection: 'row',
marginVertical: 20,
backgroundColor: 'transparent'
}
})
export default Maps
Don't forget to add dependencies to AndroidManifest.xml
In manifest tag:-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
In application tag:-
<meta-data
android:name=".google.android.geo.API_KEY"
android:value="Paste your API key from google maps [https://developers.google./maps/documentation/embed/get-api-key]"
/>