Search code examples
react-nativemapsreact-native-maps

How to make the Marker move smoothly in react-native-maps?


I have an API to get cars's position in react-native-maps.

[
  {
    "Message": "OK",
    "NumberPlate": "*****",
    "DeviceID": "60000660",
    "DriverName": "",
    "DriverLicense": "",
    "Date": "08:10:00 - 10/01/2022",
    "Lt": "latitude",
    "Ln": "longitude",
    "Address": "***, ***, ***",
    "Angle": 285,
    "CarStatus": "parking",
    "Speed": 0,
    "Acc": "off",
    "Oil": 323
  },
  .....
]

To prevent the server from crashing, I only get data every 15 seconds. And as we all know, my cars will "jump" in maps.

So is there a way to make them move smoothly?

For example they will move straight between 2 points in 15s.

This is my <MapView />

<MapView
  ref={mapRef}
  style={{width: '100%', height: '100%'}}
  initialRegion={{
    latitude: mapState.lat,
    longitude: mapState.long,
    latitudeDelta: 0.01,
    longitudeDelta: 0.01,
  }}
  onPress={() => {
    menuRef.current.snapTo(1);
    vehiclesRef.current.snapTo(2);
  }}
  showsUserLocation={true}
  showsTraffic={false}
  showsMyLocationButton={true}
  zoomEnabled={true}>
  {CarInfo.map(car => {
    return (
      <Marker
        key={car.DeviceID}
        coordinate={{
          latitude: car.Lt,
          longitude: car.Ln,
        }}
        onPress={() => vehiclesRef.current.snapTo(1)}>
        <Animated.View style={[styles.markerWrap]}>
          <Text style={styles.numberPlate} numberOfLines={1}>
            {car.NumberPlate}
          </Text>
          <Animated.Image
            source={Car}
            style={styles.marker}
            resizeMode="cover"
          />
        </Animated.View>
      </Marker>
    );
  })}
</MapView>

Solution

  • If you use react-native-maps Marker, you can see this and follow him. It works. If you want show multiple marker and want them move smoothly, you should custom a child component and use I in return(). this is my code:

    export default function CarMarker({car, onOpen}) {
      const [marker, setMarker] = useState(null);
      const [coordinate, setCoordinate] = useState(
        new AnimatedRegion({
          latitude: car.Lt || INITIAL_LAT,
          longitude: car.Ln || INITIAL_LONG,
          latitudeDelta: LATITUDE_DELTA,
          longitudeDelta: LONGITUDE_DELTA,
        }),
      );
    
      useEffect(() => {
        animateMarker();
      }, [car]);
    
      const animateMarker = () => {
        const newCoordinate = {
          latitude: car.Lt,
          longitude: car.Ln,
          latitudeDelta: LATITUDE_DELTA,
          longitudeDelta: LONGITUDE_DELTA,
        };
    
        if (Platform.OS === 'android') {
          if (marker) {
            marker.animateMarkerToCoordinate(newCoordinate, 15000);
          }
        } else {
          coordinate.timing(newCoordinate).start();
        }
      };
    
      return (
        <Marker.Animated
          key={car.DeviceID}
          ref={marker => {
            setMarker(marker);
          }}
          coordinate={coordinate}
          anchor={{x: 0.5, y: 0.5}}
          onPress={onOpen}>
          <Animated.View style={styles.markerWrap}>
            <Text style={styles.numberPlate} numberOfLines={1}>
              {car.NumberPlate}
            </Text>
            <Animated.Image source={Car} style={styles.marker} resizeMode="cover" />
          </Animated.View>
        </Marker.Animated>
      );
    }
    

    and this is my <MapView/>

    <MapView
      ref={mapRef}
      style={{width: '100%', height: '100%'}}
      initialRegion={{
        latitude: mapState.lat,
        longitude: mapState.long,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA,
      }}
      onPress={() => {
        menuRef.current.snapTo(1);
        vehiclesRef.current.snapTo(2);
      }}
      showsUserLocation={true}
      showsTraffic={false}
      showsMyLocationButton={true}
      zoomEnabled={true}>
      {CarInfo.map(car => {
        return (
          <CarMarker
            key={car.DeviceID}
            car={car}
            onOpen={() => {
              vehiclesRef.current.snapTo(1);
              setSelectedVehicle(car);
            }}
          />
        );
      })}
    </MapView>