Home > front end >  Using animateCamera in functional components in react native
Using animateCamera in functional components in react native

Time:05-10

Summary

I'm using react-native-map and trying to use animateCamera and animateMarkerToCoordinate both at the same time but couldn't animate the animateCamera at all.

The working part so far

The "red circle" in the gif I've shared below, should be moving from one location to another location with animation. I've taken advantage of this comment to be able to move marker with animation turning the code into functional component and it really worked. Moving marker gif

My aim

I want the camera also move besides marker, so that the red circle should always be felt like it is centered in the phone screen. All this should occur when I press "animate" button below.

I've tried to do the same thing to the mapview what I've done to marker.

I've created a state

const [mapRef, setMapRef] = useState(null);

and supplied connection between <MapView> and mapRef state using the below line beginning with ref

 return (
            <View style={...}>
                <MapView
                    ref= {mapRef => {setMapRef(mapRef);}}
                    initialRegion = {
                        ...
                      }
                    ...
                 />

So when the button is pressed it goes inside this function and try to work animateCamera function

function animateMarkerAndCamera() {

    let newCoordinate = {
        latitude: 32.601,
        longitude: 44.0172,
        latitudeDelta: 0.012,
        longitudeDelta: 0.012,
    };
    let Camera = {
        ...
    }
    if (myMarker) {
       
        myMarker.animateMarkerToCoordinate(newCoordinate, 4000);
        mapRef.animateCamera({Camera}, 4000)
    }

}

By the way Camera adjusted like it is mentioned in docs

 let Camera = {
        center: {
            latitude: newCoordinate.latitude,
            longitude: newCoordinate.longitude,
        },
        pitch: 2,
        heading: 20,
        zoom: 40
    }

So I'm expecting for it to animate just like it did for marker's animation, but not working.

Please tell me my fault.

Full code...

import React, {useState} from 'react'
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'
import MapView, { AnimatedRegion, MarkerAnimated } from 'react-native-maps';

const PlayScreen = (props) => {

    const [myMarker, setMyMarker] = useState(null);
    const [mapRef, setMapRef] = useState(null);

    const [coordinate, setCoordinate] = useState(new AnimatedRegion({ 
        latitude: 32.5983,
        longitude: 44.0175,
        latitudeDelta: 0.012,
        longitudeDelta:0.012,
    }));
  
     function animateMarkerAndCamera() {
        
        let newCoordinate = {
            latitude: 32.601,
            longitude: 44.0172,
            latitudeDelta: 0.012,
            longitudeDelta: 0.012,
        };
        
        if(myMarker){
            myMarker.animateMarkerToCoordinate(newCoordinate,4000);
            mapRef.animateCamera(newCoordinate, 4000);
        }
        
    }
  
        return (
            <View style={styles.container}>
                <MapView
                    ref= {mapRef => {setMapRef(mapRef);}}
                    style={styles.map}
                    initialRegion={{
                        latitude: 32.5983,
                        longitude: 44.0175,
                        latitudeDelta: 0.012,
                        longitudeDelta: 0.012,
                    }}

                >
                    <MarkerAnimated 
                         ref={marker => {
                            setMyMarker(marker);
                        }} 
                        image={require('../../../Assets/Images/curlingStone.png')}
                        coordinate={coordinate}
                    />
                        
                </MapView>
                <View style={styles.buttonContainer}>
                    <TouchableOpacity
                        onPress={() => animateMarkerAndCamera()}
                        style={[styles.bubble, styles.button]}
                    >
                        <Text>Animate</Text>
                    </TouchableOpacity>
                </View>
            </View>
        );

}

const styles = StyleSheet.create({
    container: {
        ...StyleSheet.absoluteFillObject,
        justifyContent: 'flex-end',
        alignItems: 'center',
    },
    map: {
        ...StyleSheet.absoluteFillObject,
    },
    bubble: {
        flex: 1,
        backgroundColor: 'rgba(255,255,255,0.7)',
        paddingHorizontal: 18,
        paddingVertical: 12,
        borderRadius: 20,
    },
    latlng: {
        width: 200,
        alignItems: 'stretch',
    },
    button: {
        width: 80,
        paddingHorizontal: 12,
        alignItems: 'center',
        marginHorizontal: 10,
    },
    buttonContainer: {
        flexDirection: 'row',
        marginVertical: 20,
        backgroundColor: 'transparent',
    },
});
export default PlayScreen

CodePudding user response:

So, as I've explained before, I was trying to use animateCamera and animateMarkerToCoordinate together so that it could feel like my marker, the red circle, is always at the center and only the coordinates seem to be changing.

After a little research, I've found this and made mine similar to this code. Now I obtained what I wanted to achieve.Gif is here

Changes I've made were written as comments

The code is below

import {useState, useRef} from 'react'
import ... //same as before

const PlayScreen = (props) => {
    const markerLatitude=32.5983
    const markerLongitude=44.0175
    //changed from useState to useRef
    const mapRef = useRef (null);
    const [myMarker, setMyMarker] = useState(null);
    const [coordinate, setCoordinate] = useState(new AnimatedRegion({
        latitude: markerLatitude,
        longitude: markerLongitude,
        latitudeDelta: 0.012,
        longitudeDelta: 0.012,
    }));

    function animateMarkerAndCamera() {

        let newCoordinate = {
            latitude: 32.601,
            longitude: 44.0172,
            latitudeDelta: 0.012,
            longitudeDelta: 0.012,
        };
        //camera will position itself to these coordinates.
        const newCamera= {
            center: {
                latitude: 32.601,
                longitude: 44.0172,
            },
            pitch: 0,
            heading: 0,
            //zoom: 17  --Use it when required
        }
        
        
        if (myMarker) {
            myMarker.animateMarkerToCoordinate(newCoordinate, 4000);
            //camera type, `newCamera`, used inside animateCamera
            mapRef.current.animateCamera(newCamera, {duration: 4000})
        }
        

    }

    return (
        <View style={styles.container}>
            <MapView
                ref={ mapRef } //There is also change here
                style={styles.map}
                initialRegion={{
                    latitude: 32.5983,
                    longitude: 44.0175,
                    latitudeDelta: 0.012,
                    longitudeDelta: 0.012,
                }}
                //These are newly added
                pitchEnabled ={false}
                zoomEnabled ={false}
            >
                <MarkerAnimated
                    ref={marker => {
                        setMyMarker(marker);
                    }}
                    {/*any kind of image can be replaced here */}
                    image={require('../../../Assets/Images/curlingStone.png')}
                    coordinate={coordinate}
                    
                />

            </MapView>
            <View style={styles.buttonContainer}>
                <TouchableOpacity
                    onPress={() => animateMarkerAndCamera()}
                    style={[styles.bubble, styles.button]}
                >
                    <Text>Animate</Text>
                </TouchableOpacity>
            </View>
        </View>
    );

}
export default PlayScreen

const styles = StyleSheet.create({ ... //same as before
  • Related