React native 基于本地地图的平滑位置跟踪

React native 基于本地地图的平滑位置跟踪,react-native,React Native,我建立了一个应用程序,我需要一个位置跟踪(行人)。 我正在寻找一个顺利的方法来做到这一点。 我使用watchPositionAsync,每次用户位置更改时,都会调用一个函数,在这个函数上,我使用animateToRegion,在参数和时间中使用新区域。这对该区域效果很好,相机可以平滑地跟踪用户,但当我到达一个新区域时,地图不会加载,除非我用手指移动拖动地图 有更好的办法吗?还是解决问题的方法 <MapView initialRegio

我建立了一个应用程序,我需要一个位置跟踪(行人)。 我正在寻找一个顺利的方法来做到这一点。 我使用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);
};
{this.map=ref;}
showsUserLocation={true}
style={{flex:1}}
customMapStyle={MAP\u STYLE\u SAM}
mapType={(this.state.switchValue)?'hybrid':'standard'}
提供商=“谷歌”
onRegionChangeComplete={this.onMapMove}
loadingEnable={true}
moveOnMarkerPress={false}
onPress={this.pressOnMap}
>
followUser=async()=>{
试一试{
wait Location.watchPositionAsync(地理位置选项,this.locationChanged);
}
捕获(错误){
让status=Location.getProviderStatusAsync();
如果(!status.locationServicesEnabled){
警报(“设备的全球定位活动”);
}
}
};
位置更改=(位置)=>{
常量区域={
经度:location.coords.longitude,
纬度:location.coords.latitude,
纬度三角洲:基本纬度三角洲,
经度增量:基本经度增量
};
这是哥托雷区(区域);
this.setState({currentRegion:region});
};
goToRegion=(地区)=>{
此.map.animateToRegion(region,1000*2);
};

我希望您使用的是最新版本的地图,因此不推荐使用
animateToRegion
。让状态更新驱动动画。不要为每次位置更改调用
goToRegion
。以下是您可能希望执行的操作:

componentDidUpdate(prevProps,prevState){
常量{纬度:newLat,经度:newLon}=this.state.currentRegion;
常量{纬度:oldLat,经度:oldLon}=prevState.currentRegion;
if(oldLat!==newLat | | oldLon!==newLon){
这个;
}
}
_animateCamera=()=>{
这是一张地图(
{
中心:this.state.currentRegion,//应该是{纬度,经度}
投球:10分,
},
{持续时间:750}
);
};
组件将卸载(){
this.map=null;

}
以下是整个组件@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>
    );
}
import React,{Component}来自'React';
从“react native”导入{视图、平台、WebView、TouchableOpacity、维度、开关、文本};
从“expo”导入{常量、位置、权限};
从“react native maps”导入MapView;
从“react native scalable Image”导入图像;
进口{
基本纬度三角洲,
基本经度增量,
地图(风格)(SAM),,
马克·蒙斯,
多段线,
SARAH_YELLOW,启动区域,
启动\u区域\u MONS
}来自“../../const/const”;
从“./../const/MarollesMarker”导入{MARKERS\u MAIN\u ROUTE、MARKERS\u OUT\u ROUTE、POLYLINE\u MAROLLE}”;
常量地理位置选项={精度:6,距离间隔:1};
类MarrolleMap扩展了组件{
状态={
屏幕宽度:尺寸。获取('窗口')。宽度,
位置:空,
errorMessage:null,
switchValue:false,
马克斯:错,
标记路径:false,
markerID:“”,
currentRegion:START_区域,
markerLoc:未定义,
prevPos:null,
curPos:{纬度:37.420814,经度:-122.081949},
策展人:45,
纬度德尔塔:0.0922,
纵向德尔塔:0.0421,
};
//----------------地点授权-------------
getPermissionLocation=async()=>{
试一试{
让{status}=wait Permissions.askAsync(Permissions.LOCATION);
如果(状态!=“已授予”){
这是我的国家({
errorMessage:'访问位置的权限被拒绝',
});
}
}
捕获(错误){
console.log(错误);
}
if(Platform.OS==='android'&&!Constants.isDevice){
log(“在设备上试用”);
这是我的国家({
errorMessage:“哦,这在Android模拟器中的草图上不起作用。请在您的设备上试用!”,
});
}否则{
这是。_getLocationAsync();
//这辆车还没有回来
}
};
_getLocationAsync=async()=>{
//一个执行者正在安装一个计时器
if(Platform.OS==='android'&&!Constants.isDevice){
log(“在设备上试用”);
这是我的国家({
errorMessage:“哦,这在Android模拟器中的草图上不起作用。请在您的设备上试用!”,
});
}否则{
试一试{
let location=await location.getCurrentPositionAsync({});
这是我的国家({
当前区域:{
经度:location.coords.longitude,
纬度:location.coords.latitude,
经度增量:基本经度增量,
纬度三角洲:基本纬度三角洲
}
});
//this.setState({location});
}
捕获(错误){
让status=Location.getProviderStatusAsync();
如果(!status.locationServicesEnabled){
警报(“设备的全球定位活动”);
}
}
}
};
//------------------本地化-------------------
followUser=async()=>{
试一试{
wait Location.watchPositionAsync(地理位置选项,this.locationChanged);
}
捕获(错误){
让status=Location.getProviderStatusAsync();
如果(!status.locationServicesEnabled){
警报(“设备的全球定位活动”);
}
}
};
位置更改=(位置)=>{
常量区域={
朗吉特