You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Native中Expo Location API定位及地图初始区域调整方法

问题2:为地图应用添加“切换到当前位置”功能

结合你提供的现有代码,我帮你完成了修改:实现打开应用自动定位到当前位置,同时添加按钮手动触发定位。以下是完整的修改后代码,关键修改处都加了注释:

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';
// 新增:导入Expo Location模块
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,
 // 新增:添加currentRegion状态,初始值为东京站区域
 currentRegion: {
   latitude: 35.681236,
   longitude: 139.767125,
   latitudeDelta: 0.02,
   longitudeDelta: 0.02,
 }
 }
 }

 // 新增:获取当前位置并更新地图区域的函数
 getCurrentLocationAndUpdateMap = async () => {
   try {
     // 请求位置权限
     let { status } = await Location.requestForegroundPermissionsAsync();
     if (status !== 'granted') {
       alert('位置权限被拒绝,无法获取当前位置');
       return;
     }

     // 获取当前位置
     let location = await Location.getCurrentPositionAsync({});
     // 更新地图区域到当前位置
     this.setState({
       currentRegion: {
         latitude: location.coords.latitude,
         longitude: location.coords.longitude,
         latitudeDelta: 0.02,
         longitudeDelta: 0.02,
       }
     });
   } catch (error) {
     console.error('获取位置失败:', error);
     alert('获取当前位置失败,请重试');
   }
 }

 // 新增:组件挂载时自动调用定位函数,实现打开应用自动定位
 componentDidMount() {
   this.getCurrentLocationAndUpdateMap();
 }

 //地图画面变更时计算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函数的参数
 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}>
 {/* 修改:将initialRegion替换为region,绑定state中的currentRegion,支持动态更新地图位置 */}
 <MapView 
   onRegionChangeComplete={this.onRegionChangeComplete} 
   style={styles.mapView}
   region={this.state.currentRegion}
 >
 { 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>
 {/* 新增:添加切换到当前位置的按钮 */}
 <TouchableOpacity onPress={this.getCurrentLocationAndUpdateMap} style={[styles.button, {marginLeft: 10}]} >
 <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',
 },
 });

关键修改说明:

  1. 导入Expo Location:添加了位置获取和权限请求的依赖模块
  2. 新增currentRegion状态:替代原来的initialRegion,因为initialRegion仅在初始化时生效,region支持动态更新地图显示区域
  3. 定位函数实现getCurrentLocationAndUpdateMap处理权限校验、位置获取和地图区域更新
  4. 自动定位触发:在componentDidMount中调用定位函数,实现打开应用自动定位
  5. 手动定位按钮:新增按钮让用户可以随时触发定位操作

内容的提问来源于stack exchange,提问作者Shunsuke

火山引擎 最新活动