我需要一个位置跟踪(针对行人)时构建了一个应用程序。 我正在寻找一种顺利的方式来做到这一点。 我使用watchPositionAsync,每次用户位置更改时,都会调用一个函数,并且在该函数上,我将animateToRegion与参数和时间的新区域一起使用。在该区域内效果很好,相机可以平稳地跟踪用户,但是除非我用手指移动拖动地图,否则到达新区域时地图不会加载。
还有更好的方法吗?或解决此问题的方法?
<MapView
initialRegion={this.state.currentRegion}
ref={ref => { this.map = ref; }}
showsUserLocation={true}
style={{ flex: 1 }}
customMapStyle={MAP_STYLE_SAM}
mapType={(this.state.switchValue) ? 'hybrid':'standard'}
provider='google'
onRegionChangeComplete={this.onMapMove}
loadingEnable={true}
moveOnMarkerPress={false}
onPress={this.pressOnMap}
>
followUser = async () => {
try {
await Location.watchPositionAsync(GEOLOCATION_OPTIONS, this.locationChanged);
}
catch (error) {
let status = Location.getProviderStatusAsync();
if (!status.locationServicesEnabled) {
alert('Veuillez activer la géolocalisation de votre appareil.');
}
}
};
locationChanged = (location) => {
const region = {
longitude: location.coords.longitude,
latitude: location.coords.latitude,
latitudeDelta: BASIC_LATITUDE_DELTA,
longitudeDelta: BASIC_LONGITUDE_DELTA
};
this.goToRegion(region);
this.setState({ currentRegion: region });
};
goToRegion = (region) => {
this.map.animateToRegion(region,1000*2);
};
答案 0 :(得分:0)
我希望您使用的是最新版本的地图,因此animateToRegion
已过时。让状态更新驱动动画。请勿为每次位置更改致电goToRegion
。这是您可能想做的:
componentDidUpdate(prevProps, prevState) {
const { latitude: newLat, longitude: newLon } = this.state.currentRegion;
const { latitude: oldLat, longitude: oldLon } = prevState.currentRegion;
if (oldLat !== newLat || oldLon !== newLon) {
this._animateCamera();
}
}
_animateCamera = () => {
this.map.animateCamera(
{
center: this.state.currentRegion, // should be { latitude, longitude }
pitch: 10,
},
{ duration: 750 }
);
};
componentWillUnmount() {
this.map = null;
}
答案 1 :(得分:0)
这是@Ziyo的全部内容,并有您的建议:
import React, { Component } from 'react';
import {View, Platform, WebView, TouchableOpacity, Dimensions, Switch, Text} from 'react-native';
import {Constants, Location, Permissions } from 'expo';
import MapView from 'react-native-maps';
import Image from 'react-native-scalable-image';
import {
BASIC_LATITUDE_DELTA,
BASIC_LONGITUDE_DELTA,
MAP_STYLE_SAM,
MARKERS_MONS,
POLYLINE_MONS_COORD,
SARAH_YELLOW, START_REGION,
START_REGION_MONS
} from "../../const/Const";
import {MARKERS_MAIN_ROUTE, MARKERS_OUT_ROUTE, POLYLINE_MAROLLE} from "../../const/MarollesMarker";
const GEOLOCATION_OPTIONS = { accuracy: 6, distanceInterval: 1};
class MarrolleMap extends Component {
state = {
screenWidth: Dimensions.get('window').width,
location: null,
errorMessage: null,
switchValue: false,
markerSelected : false,
markerIsMainRoute: false,
markerID: '',
currentRegion: START_REGION,
markerLoc: undefined,
prevPos: null,
curPos: { latitude: 37.420814, longitude: -122.081949 },
curAng: 45,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
};
//----------------location authorisations-------------
getPermissionLocation = async () => {
try {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
}
}
catch (error) {
console.log(error);
}
if (Platform.OS === 'android' && !Constants.isDevice) {
console.log('try it on device');
this.setState({
errorMessage: 'Oops, this will not work on Sketch in an Android emulator. Try it on your device!',
});
} else {
this._getLocationAsync();
//ne se lance pas car il y a un return dans le
}
};
_getLocationAsync = async () => {
// a executer dans didmount apres 1s (timer)
if (Platform.OS === 'android' && !Constants.isDevice) {
console.log('try it on device');
this.setState({
errorMessage: 'Oops, this will not work on Sketch in an Android emulator. Try it on your device!',
});
} else {
try {
let location = await Location.getCurrentPositionAsync({});
this.setState({
currentRegion : {
longitude: location.coords.longitude,
latitude: location.coords.latitude,
longitudeDelta: BASIC_LONGITUDE_DELTA,
latitudeDelta: BASIC_LATITUDE_DELTA
}
});
//this.setState({ location });
}
catch (error) {
let status = Location.getProviderStatusAsync();
if (!status.locationServicesEnabled) {
alert('Veuillez activer la géolocalisation de votre appareil.');
}
}
}
};
//------------------localisations-------------------
followUser = async () => {
try {
await Location.watchPositionAsync(GEOLOCATION_OPTIONS, this.locationChanged);
}
catch (error) {
let status = Location.getProviderStatusAsync();
if (!status.locationServicesEnabled) {
alert('Veuillez activer la géolocalisation de votre appareil.');
}
}
};
locationChanged = (location) => {
const region = {
longitude: location.coords.longitude,
latitude: location.coords.latitude,
latitudeDelta: BASIC_LATITUDE_DELTA,
longitudeDelta: BASIC_LONGITUDE_DELTA
};
this.setState({ currentRegion: region });
};
componentDidUpdate = async (prevProps, prevState) => {
console.log("didUpdate");
const {latitude: newLat, longitude: newLong} = this.state.currentRegion;
const { latitude: oldLat, longitude: oldLong } = prevState.currentRegion;
if ( (oldLat !== newLat) || (oldLong !== newLong) ) {
this._animateCamera();
}
};
componentWillUnmount() {
this.map = null;
}
_animateCamera = () => {
this.map.animateCamera(
{
center : { latitude: 50.8435, longitude: 4.3488 },
pitch: 10,
},
{ duration: 750 }
);
};
followHeading = async () => {
try {
await Location.watchHeadingAsync(this.headingChanged);
}
catch (error) {
console.log(error)
}
};
headingChanged = (heading) => {
console.log(heading)
};
//-------------------------map-------------------------
onMapReady = () => {
console.log('map ready')
};
onMapMove = (region) => {
//code exeuted each time the map move, we get this region values on states
//console.log('move');
};
pressMainMarker = (coordinate, position) => {
/*faudra faire en sorte de savoir avant de taper sur le marker, vers quel idmarker on
s'approche et seter, pour afficher la winodows info en question*/
const coord = coordinate.nativeEvent.coordinate;
const id = coordinate.nativeEvent.id;
this.setState({
markerID: id,
markerSelected: true,
markerIsMainRoute: true,
markerLoc: coord
});
console.log(this.state.markerID);
};
pressOutRouteMarker = (coordinate, position) => {
const coord = coordinate.nativeEvent.coordinate;
const id = coordinate.nativeEvent.id;
this.setState({
markerID: id,
markerSelected: true,
markerIsMainRoute: false,
markerLoc: coord
});
console.log(this.state.markerID);
};
resetCurrentMarkerState = () => {
this.setState({
markerSelected: false,
markerIsMainRoute: false,
});
};
pressOnMap = (event) => {
const lat = event.nativeEvent.coordinate.latitude;
const long = event.nativeEvent.coordinate.longitude;
//console.log(`{ latitude: ${lat}, longitude: ${long}},`)*/
this.setState({
currentRegion: {
longitude: long,
latitude: lat,
longitudeDelta: BASIC_LONGITUDE_DELTA,
latitudeDelta: BASIC_LATITUDE_DELTA
}
});
console.log(this.state.currentRegion);
this.resetCurrentMarkerState();
};
pressOnSwitch = (value) => {
this.setState({switchValue: value});
};
componentWillMount() {
this.getPermissionLocation();
}
render() {
return (
<View style={{ flex: 1 , backgroundColor: '#fff'}}>
<View style={{top: 0}}>
</View>
<MapView
initialRegion={{...this.state.curPos,
latitudeDelta: this.state.latitudeDelta,
longitudeDelta: this.state.longitudeDelta}}
ref={ref => { this.map = ref; }}
showsUserLocation={true}
style={{ flex: 1 }}
customMapStyle={MAP_STYLE_SAM}
mapType={(this.state.switchValue) ? 'hybrid':'standard'}
provider='google'
onRegionChangeComplete={this.onMapMove}
loadingEnable={true}
moveOnMarkerPress={false}
onPress={this.pressOnMap}
onMapReady={this.onMapReady}
>
{MARKERS_MAIN_ROUTE.map(marker =>(
<MapView.Marker
key={marker.key}
coordinate={marker.coordinate}
title={marker.title}
identifier={marker.identifier}
description={marker.description}
onPress={this.pressMainMarker}
onDeselect={() => alert('deselect')}
>
<Image
width={30}
source={require('../../assets/CtrlMap/Scr005_Pointeur_Parcours.png')}
/>
<MapView.Callout
style={{backgroundColor: '#4f3dff', width: 200, height: 100, borderRadius: 50}}
tooltip={true}
>
<WebView
originWhitelist={['*']}
source={{html: '<h1>Marolles</h1>'}}
/>
<Text>{this.state.markerID}</Text>
</MapView.Callout>
</MapView.Marker>
))}
{MARKERS_OUT_ROUTE.map(marker =>(
<MapView.Marker
key={marker.key}
coordinate={marker.coordinate}
title={marker.title}
identifier={marker.identifier}
description={marker.description}
onPress={this.pressOutRouteMarker}
onDeselect={() => alert('deselect')}
>
<Image
width={30}
source={require('../../assets/CtrlMap/Scr005_Pointeur_horsParcours.png')}
/>
<MapView.Callout
style={{backgroundColor: '#4f3dff', width: 200, height: 100, borderRadius: 50}}
tooltip={true}
>
<WebView
originWhitelist={['*']}
source={{html: '<h1>Marolles</h1>'}}
/>
<Text>{this.state.markerID}</Text>
</MapView.Callout>
</MapView.Marker>
))}
<MapView.Polyline
coordinates={POLYLINE_MAROLLE}
strokeColor={SARAH_YELLOW}
fillColor={SARAH_YELLOW}
strokeWidth={10}
>
</MapView.Polyline>
</MapView>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={[styles.buttonStart,{ width: 0.175 * this.state.screenWidth}]}
activeOpacity={0.5}
onPress={this.followUser}
>
<Image
width={0.175 * this.state.screenWidth}
source={require('../../assets/CtrlMap/scr005_goPlayeurButton.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.switchContainer}>
<Switch
onValueChange={this.pressOnSwitch}
value={this.state.switchValue}
trackColor={{true : '#F2BF0573', false: '#F2BF050D'}}
thumbColor={'#FFF'}
/>
</View>
<View style={styles.containerOptionBtn} >
<TouchableOpacity
style={[styles.buttonOption,{width: 0.05 * this.state.screenWidth}]}
activeOpacity={0.5}
onPress={() => console.log('nique tout')}
>
<Image
width={0.05 * this.state.screenWidth}
source={require('../../assets/CtrlMascotChoice/Scr002_Crenage.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.containerExitBtn} >
<TouchableOpacity
style={[styles.buttonExit,{width: 0.075 * this.state.screenWidth}]}
activeOpacity={0.5}
onPress={() => console.log('nique tout')}
>
<Image
width={0.075 * this.state.screenWidth}
source={require('../../assets/CtrlMap/Quitter_bleu.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}
常量样式= { buttonContainer:{ 位置:“绝对”, 底部:10, 右:10 }, 段落:{ 保证金:10, fontSize:18, textAlign:'居中', backgroundColor:“#FFF” }, switchContainer:{ 位置:“绝对”, 底部:25, 左:10 }, containerOptionBtn:{ 位置:“绝对”, 最高:35, 左:15, }, buttonOption:{ alignItems:'flex-end', paddingRight:5 }, containerExitBtn:{ 位置:“绝对”, 最高:30 对:15, }, buttonExit:{ alignItems:'flex-end', paddingRight:5 } };
导出默认的MarrolleMap;