最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to draw polygon on react native maps with many points(latitude and longitude)? - Stack Overflow

programmeradmin0浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 2

You 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]"
/>
发布评论

评论列表(0)

  1. 暂无评论