How can i update react-native-map marker smoothly as location changes?

189 Views Asked by At

I am having issues animating the map marker on react-native-maps application. the marker stays in the center and do not move with the blue dot. and the map screen changes abruptly.

I am using the android emulator route simulator to simulate moving around.

What I really want to achieve is to update the map marker on the map screen smooothly just like the default blue dot is doing as the current location changes.

This is what I've tried: MapScreen.js

const [
    mapRef,
    requestLocationPermission,
    position,
    watchId,
    subscribeLocationLocation,
    getOneTimeLocation,
    setPosition,
  ] = useLocation();
  const [darkMode, setDarkMode] = useState(theme.dark);

  useEffect(() => {
    requestLocationPermission();
    subscribeLocationLocation(user._id);

    return () => {
      Geolocation.clearWatch(watchId);
    };
  }, []);

  const toggleDarkMode = () => setDarkMode(!darkMode);
  console.log(darkMode);

  return (
    <View style={styles(colors).mapContainerStyles}>
      <StatusBar backgroundColor="transparent" translucent={true} />
      <View style={styles(colors).container}>
        <MapView
          userInterfaceStyle={darkMode ? 'dark' : 'light'}
          key={darkMode}
          ref={mapRef}
          region={position}
          onRegionChange={() => position}
          onRegionChangeComplete={position => setPosition(position)}
          style={styles(colors).mapStyle}
          initialRegion={position}
          customMapStyle={darkMode ? mapStyle : {}}
          showsUserLocation={true}
          showsMyLocationButton={true}
          followsUserLocation={true}
          showsCompass={true}
          scrollEnabled={true}
          zoomEnabled={true}
          pitchEnabled={true}
          rotateEnabled={true}>
          <Marker
            draggable
            coordinate={{
              latitude: position.latitude,
              longitude: position.longitude,
            }}
            onDragEnd={e =>
              Alert.alert(JSON.stringify(e.nativeEvent.coordinate))
            }
            pinColor="green"
            title={'Test Marker'}
            description={`${position.latitude}, ${position.longitude}`}
          />
        </MapView>
        <View style={styles(colors).darkModeStyles}>
          <DefaultText
            textColor={darkMode ? 'white' : 'black'}
            textStyle={styles(colors).darkModeTextStyles}
            bold={true}
            textString={`${darkMode ? 'Light' : 'Dark'} Mode`}
          />
          <Switch
            trackColor={{false: '#767577', true: '#81b0ff'}}
            thumbColor={darkMode ? '#f5dd4b' : '#f4f3f4'}
            ios_backgroundColor="#3e3e3e"
            onValueChange={toggleDarkMode}
            value={darkMode}
          />
          {/* <Button onPress={toggleDarkMode} title="Dark Mode" /> */}
        </View>
      </View>
      <View style={styles(colors).informationStyles}>
        <Button
          onPress={() => getOneTimeLocation()}
          title="Get current location"
        />
        <Information navigation={navigation} />
      </View>
    </View>
  );
};

useLocation.js

import React, {useState} from 'react';

import {PermissionsAndroid, Platform} from 'react-native';
import Geolocation from '@react-native-community/geolocation';
import socket from './socket';

export default function useLocation() {
  //   const [currentLongitude, setCurrentLongitude] = useState(0);
  //   const [currentLatitude, setCurrentLatitude] = useState(0);
  const [locationStatus, setLocationStatus] = useState('');
  const [watchId, setWatchId] = useState(null);

  const mapRef = React.useRef(null);

  const [position, setPosition] = useState({
    latitude: 9.077751,
    longitude: 8.6774567,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
  });

  const requestLocationPermission = async () => {
    console.log('REQUESTING LOCATION PERMISSION!!!!!');
    if (Platform.OS === 'ios') {
      getOneTimeLocation();
      // subscribeLocationLocation();
    } else {
      console.log('INSIDE OF ANDROID PLATFORM');
      try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          {
            title: 'Location Access Required',
            message: 'This App needs to Access your location',
          },
        );
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          console.log('ANDROID PERMISSION HAS BEEN GRANTED!!!');
          //To Check, If Permission is granted
          getOneTimeLocation();
          // subscribeLocationLocation();
        } else {
          setLocationStatus('Permission Denied');
        }
      } catch (err) {
        console.warn(err);
      }
    }
  };

  const getOneTimeLocation = () => {
    console.log('GETTING ONE TIME LOCATION!!!');
    setLocationStatus('Getting Location ...');
    Geolocation.getCurrentPosition(
      //Will give you the current location
      pos => {
        console.log('===============================');
        console.log(pos.coords);
        console.log('===============================');
        const crd = pos.coords;
        setLocationStatus('You are Here');
        //getting the Latitude from the location json
        // setCurrentLongitude(crd.longitude);
        // //Setting state Longitude to re re-render the Longitude Text
        // setCurrentLatitude(crd.latitude);

        console.log('SETTING NEW POSITION GOTTEN FROM DEVICE!!!');
        setPosition({
          latitude: crd.latitude,
          longitude: crd.longitude,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        });

        mapRef.current?.animateToRegion(position);
        //Setting state Latitude to re re-render the Longitude Text
      },
      error => {
        setLocationStatus(error.message);
        console.log(error);
      },
      {enableHighAccuracy: true, timeout: 25000, maximumAge: 3600000},
    );
  };

  const subscribeLocationLocation = userId => {
    console.log('SUBSCRIBING TO LOCATION!!!');
    const watchid = Geolocation.watchPosition(
      pos => {
        console.log(pos);
        // setLocationStatus('You are Here');
        const crd = pos.coords;
        console.log(crd);

        setPosition({
          latitude: crd.latitude,
          longitude: crd.longitude,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        });
        // mapRef.current?.animateToRegion(position);
        //Setting state Latitude to re re-render the Longitude Text

        if (
          position.latitude == crd.latitude &&
          position.longitude == crd.longitude
        ) {
          console.log('Same position as before');
        } else {
          socket.emit('updateLocation', {position, userId});
        }
      },
      error => {
        setLocationStatus(error.message);
      },
      {
        enableHighAccuracy: true,
        distanceFilter: 5000,
        interval: 5000,
        fastestInterval: 2000,
      },
    );

    setWatchId(watchid);
  };

  return [
    mapRef,
    requestLocationPermission,
    position,
    watchId,
    subscribeLocationLocation,
    getOneTimeLocation,
    setPosition,
  ];
}

enter image description here

1

There are 1 best solutions below

1
Amine Zouinekh On

check-in mapview

onUserLocationChange={async (e) => {{/* you can her update the marker but that will make the blue point always appear if u want to remove it u can set  showsUserLocation={false} and use  const cordsMarkerLocation = await Location.watchPositionAsync(
          { accuracy: Location.Accuracy.High },
          (location) => {
            setLocationMarker(location.coords);
          }
        );*/}}