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', }, });
关键修改说明:
- 导入Expo Location:添加了位置获取和权限请求的依赖模块
- 新增currentRegion状态:替代原来的
initialRegion,因为initialRegion仅在初始化时生效,region支持动态更新地图显示区域 - 定位函数实现:
getCurrentLocationAndUpdateMap处理权限校验、位置获取和地图区域更新 - 自动定位触发:在
componentDidMount中调用定位函数,实现打开应用自动定位 - 手动定位按钮:新增按钮让用户可以随时触发定位操作
内容的提问来源于stack exchange,提问作者Shunsuke




