简体   繁体   中英

How can I get current location for using Expo location API with React Native?

Now I am making the map that we can get the location of kindergartens,but now initialRegion is Tokyo station. I would like to adjust the map as getting current location when user open the app,or something button is pressed.How can I add the code??

below is current code,and it can get the location of kindergartens when the button is pressed.

import React from 'react';
import { StyleSheet, Text, View,TouchableOpacity } from 'react-native';
import MapView from 'react-native-maps';
import {point} from '@turf/helpers';
import destination from '@turf/destination';

export default class App extends React.Component {
    constructor(props) {
        super(props) 
        this.state = {
            elements: [],
            south:null,
            west:null,
            north:null,
            east:null,

        }
    }

        //地図の画面が変更されるたびにbboxを計算
        onRegionChangeComplete = (region) => {
        //111キロメートルから中心点から縦幅、横幅を計算
        const center = point([region.longitude, region.latitude])
        const verticalMeter = 111 * region.latitudeDelta / 2
        const horizontalMeter = 111 *region.longitudeDelta / 2
        //実際の距離を計算
        const options = {units: 'kilometers'}
        const south = destination(center,verticalMeter,180,options)
        const west = destination(center,horizontalMeter,-90,options)
        const north = destination(center,verticalMeter,0,options)
        const east = destination(center,horizontalMeter,90,options)
        //計算結果(GeoJson)からbboxを保存する
        this.setState({
            south:south.geometry.coordinates[1],
            west:west.geometry.coordinates[0],
            north:north.geometry.coordinates[1],
            east:east.geometry.coordinates[0],
        })
    }

        fetchToilet = async  () => {
            const south = this.state.south
            const west = this.state.west
            const north = this.state.north
            const east = this.state.east
            //テンプレートリテラルを使ってbboxを展開
            const body = `
            [out:json];
            (
                node
                [amenity=kindergarten]
                (${south},${west},${north},${east});

            );
            out;
            `

            //fetch関数に渡すoptionを指定
            const options = {
                method: 'POST',
                body: body
            }

            //fetch関数でOverpass APIのエントリポイントにアクセスし、取得したJSONを保存
            try {
                const response = await fetch('https://overpass-api.de/api/interpreter',options)
                const json = await response.json()
                this.setState({elements: json.elements})
            }catch (e) {
            console.log(e)
        
            }
}
    render() {
        return (
            <View style ={styles.container}>
            <MapView
            onRegionChangeComplete={this.onRegionChangeComplete}
                style={styles.mapView}
                initialRegion={{
                    latitude: 35.681236,
                    longitude: 139.767125,
                    latitudeDelta: 0.02, //小さくなるほどズーム
                    longitudeDelta: 0.02,
                }}>

                {
                    this.state.elements.map((element) =>{

                        let title= "保育園"
                        if (element.tags["name"] !==undefined) {
                            title = element.tags["name"]
                        }
                        return (<MapView.Marker
                            coordinate={{
                                latitude: element.lat,
                                longitude: element.lon,
                            }}
                            title={title}
                            key={"id_" + element.id}
                        />)
                    })

                }

                    </MapView>


            <View style ={styles.buttonContainer}>
            <TouchableOpacity
            onPress={() => this.fetchToilet()}
            style={styles.button}
            >
            <Text style={styles.buttonItem}>保育園取得</Text>
            </TouchableOpacity>
            </View>
            </View>
    
        );
    }
}

const styles = StyleSheet.create({

    container: {
      flex: 1,
      backgroundColor:'#fff',
      alignItems: 'center',
      justifyContent: 'flex-end',
      
    },
  
    mapView: {
      ...StyleSheet.absoluteFillObject,
    },
  
    

    buttonContainer: {
       flexDirection:'row',
       marginVertical:20,
       backgroundColor:'transparent',
       alignItems:'center',
    },
  
    button: {
        width:150,
        alignItems:'center',
        justifyContent:'center',
        backgroundColor:'rgba(255,235,255,0.7)',
        paddingHorizontal:18,
        paddingVertical:12,
        borderRadius:20,
    },

    buttonItem: {
        textAlign:'center',
    },


  });

You can use expo-location package to get user current location in expo app. Here is officials docs .


Link to Expo Snack Example


You added this code to componentDidMount or useEffect hook to get user Location every time the app is opened.

import * as Location from "expo-location";
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import MapView from 'react-native-maps';
import { point } from '@turf/helpers';
import destination from '@turf/destination';
import * as Location from 'expo-location';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      elements: [],
      south: null,
      west: null,
      north: null,
      east: null,
      latitude: 35.681236,
      longitude: 139.767125,
    };
  }

  updateState(location) {
    this.setState({
      ...this.state,
      latitude: location.coords.latitude,
      longitude: location.coords.longitude,
    });
  }

  async componentDidMount() {
    try {
      let { status } = await Location.requestPermissionsAsync();
      if (status !== 'granted') {
        return;
      }
      let location = await Location.getCurrentPositionAsync({});
      this.updateState(location);
    } catch (error) {
      console.log(error);
    }
  }

  onRegionChangeComplete = (region) => {
    const center = point([region.longitude, region.latitude]);
    const verticalMeter = (111 * region.latitudeDelta) / 2;
    const horizontalMeter = (111 * region.longitudeDelta) / 2;
    const options = { units: 'kilometers' };
    const south = destination(center, verticalMeter, 180, options);
    const west = destination(center, horizontalMeter, -90, options);
    const north = destination(center, verticalMeter, 0, options);
    const east = destination(center, horizontalMeter, 90, options);
    this.setState({
      south: south.geometry.coordinates[1],
      west: west.geometry.coordinates[0],
      north: north.geometry.coordinates[1],
      east: east.geometry.coordinates[0],
    });
  };

  fetchToilet = async () => {
    const south = this.state.south;
    const west = this.state.west;
    const north = this.state.north;
    const east = this.state.east;
    const body = `
            [out:json];
            (
                node
                [amenity=kindergarten]
                (${south},${west},${north},${east});

            );
            out;
            `;

    const options = {
      method: 'POST',
      body: body,
    };

    try {
      const response = await fetch(
        'https://overpass-api.de/api/interpreter',
        options
      );
      const json = await response.json();
      this.setState({ elements: json.elements });
    } catch (e) {
      console.log(e);
    }
  };
  render() {
    return (
      <View style={styles.container}>
        <MapView
          onRegionChangeComplete={this.onRegionChangeComplete}
          style={styles.mapView}
          showsUserLocation
          initialRegion={{
            latitude: this.state.latitude,
            longitude: this.state.longitude,
            latitudeDelta: 0.02, 
            longitudeDelta: 0.02,
          }}>
          {this.state.elements.map((element) => {
            let title = '保育園';
            if (element.tags['name'] !== undefined) {
              title = element.tags['name'];
            }
            return (
              <MapView.Marker
                coordinate={{
                  latitude: element.lat,
                  longitude: element.lon,
                }}
                title={title}
                key={'id_' + element.id}
              />
            );
          })}
        </MapView>

        <View style={styles.buttonContainer}>
          <TouchableOpacity
            onPress={() => this.fetchToilet()}
            style={styles.button}>
            <Text style={styles.buttonItem}>保育園取得</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'flex-end',
  },

  mapView: {
    ...StyleSheet.absoluteFillObject,
  },

  buttonContainer: {
    flexDirection: 'row',
    marginVertical: 20,
    backgroundColor: 'transparent',
    alignItems: 'center',
  },

  button: {
    width: 150,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'rgba(255,235,255,0.7)',
    paddingHorizontal: 18,
    paddingVertical: 12,
    borderRadius: 20,
  },

  buttonItem: {
    textAlign: 'center',
  },
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM