Raikumar Khangembam
Raikumar Khangembam

Reputation: 1008

MapView map glitches when trying to move the pin and marker -- React-native

I am trying to create a Swiggy/Zomato/FoodPanda like the app, I am trying to get user location or set delivery location on to the map.

The issue is happening on Android.

But I am not experiencing a smoothness when moving marker position, especially when zooming in and zooming out.

Map glitches when trying to move pin marker position

please suggest me for improvement and for to get smoothness experience.

I am trying a lot of logic but not getting any desired performance.

Here is my implemented code,

This is my initial setup on constructor

constructor(props) {
    super(props);
    this.latDelta = 0.00922 * 1.5;
    this.longDelta = 0.00421 * 1.5;
    this.state = {
      visible: false,

      address: {},

      lastLat: 24.8076793,
      lastLong: 93.9360916,
      mapRegion: new AnimatedRegion({
        latitude: 24.8076793,
        longitude: 93.9360916,
        latitudeDelta: this.latDelta,
        longitudeDelta: this.longDelta
      }),
      marker: null,
      region: new AnimatedRegion({
        latitudeDelta: this.latDelta,
        longitudeDelta: this.longDelta,
        latitude: 24.8076793,
        longitude: 93.9360916
      }),
      autoGeoMarker: {
        latitude: 24.8076793,
        longitude: 93.9360916,
        autoMapAddress: '',
        autoMapArea: ''
      },
      setGeoMarker: {
        latitude: 24.8076793,
        longitude: 93.9360916,
        setMapAddress: '',
        setMapArea: ''
      },
      mapIndicator: false,
      mapAddress: '',
      mapArea: '',
      //-----
      indicator: true,
      searchModal: false
    };
  }
  componentDidMount() {
    
    this.getPermissionLocation();
  }

Here I am asking for permission

getPermissionLocation = () => {
    try {
      request(
        Platform.select({
          android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
          ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
        })
      ).then(res => {
        if (res == 'granted') {
          this.setState({
            searchModal: false
          });
          Geolocation.getCurrentPosition(
            //Will give you the current location
            position => {
              let region = {
                latitude: position.coords.latitude,
                longitude: position.coords.longitude,
                latitudeDelta: this.latDelta,
                longitudeDelta: this.longDelta
              };
              Alert.alert('', 'Pin Your Delivery point by moving map');

              this.setState({
                autoGeoMarker: region,
                mapIndicator: false,
                indicator: false
              });

              this.onRegionChange(region);
              this.getAutoDetectAddress(region.latitude, region.longitude);
            },
            error => {
              //setLocationStatus(error.message);
              console.log('error ... 1 ' + error.message);
            },
            {
              enableHighAccuracy: false,
              timeout: 30000,
              maximumAge: 1000
            }
          );

        } else {
          console.log('Location is not enabled');

          Alert.alert(
            'Enable Your Location:',
            'Can not proceed, Please allow your Location permissioin.',
            [{ text: 'OK', onPress: () => RNRestart.Restart() }]
          );
        }
      });
    } catch (error) {
      console.log('location set error:', error);
    }
  };

    //Get Auto Geolocation address
    getAutoDetectAddress = (latitude, longitude) => {
      Geocoder.from(latitude, longitude)
        .then(json => {
          let region = {
            latitude: latitude,
            longitude: longitude,
            latitudeDelta: this.latDelta,
            longitudeDelta: this.longDelta,
            autoMapAddress: json.results[0].formatted_address,
            autoMapArea: json.results[0].address_components[1].short_name
          };
          this.setState({
            autoGeoMarker: region
          });
        })
        .catch(error => console.warn(error));
  
      //-----------------------
    };

  onRegionChange = region => {
    this.setState({
      region: region,
      lastLat: region.latitude,
      lastLong: region.longitude
    });

    this.getAddressInfo(region.latitude, region.longitude);
  };

  getAddressInfo = (latitude, longitude) => {
    Geocoder.from(latitude, longitude)
      .then(json => {
        this.setState({
          mapAddress: json.results[0].formatted_address,
          mapArea: json.results[0].address_components[1].short_name
        });

        let region = {
          latitude: json.results[0].geometry.location.lat,
          longitude: json.results[0].geometry.location.lng,
          latitudeDelta: this.latDelta,
          longitudeDelta: this.longDelta,
          setMapAddress: json.results[0].formatted_address,
          setMapArea: json.results[0].address_components[1].short_name
        };

        this.setState({
          setGeoMarker: region
        });
      })
      .catch(error => console.warn(error));
  };


  render() {
    return this.state.indicator ? (
      <View style={{ flex: 1 }}>
        <ActivityIndicator size="large" color="#ff6a00" />
      </View>
    ) : (
      <View style={{ flex: 1, flexDirection: 'column' }}>
        <StatusBar backgroundColor="#ff6a00" />
        
        <View style={styles.map}>
          <MapView
            style={styles.map}
            region={this.state.region}
            onRegionChangeComplete={this.onRegionChange}
          />

          <View
            style={{
              flex: 1,
              flexDirection: 'row',
              alignItems: 'center',
              position: 'absolute',
              top: '4%',
              left: '-3%'
            }}
          >
            <TouchableOpacity
              onPress={() => {
                {
                  this.props.navigation.navigate('HomeScreen');
                }
              }}
            >
              <Image
                style={{ width: 71, height: 51 }}
                source={require('../../assets/app/mapback.png')}
              />
            </TouchableOpacity>
          </View>

       
          <View style={styles.markerFixed}>
            <Image style={styles.marker} source={marker} />
          </View>
       
        </View>
        <View
          style={{
            flex: 1,
            padding: 4,
            backgroundColor: '#FFFFFF'
            // borderTopColor: 'black',
            // borderTopWidth: 1
          }}
        >
          <View
            style={{
              flex: 1,
              flexDirection: 'row',
              alignItems: 'center',
              marginTop: 15,
              marginLeft: 20
            }}
          >
            <View
              style={{ flex: 0.8, alignItems: 'center', flexDirection: 'row' }}
            >
              <Image
                style={{ width: 15, height: 20 }}
                source={require('../../assets/app/mapmark.png')}
              />
              <Text
                style={{
                  fontSize: 18,
                  marginLeft: 15,
                  fontFamily: 'Nunito-Black'
                }}
              >
                {this.state.mapArea}
              </Text>
            </View>

          
          </View>
          <Text
            style={{
              marginTop: 20,
              marginLeft: 20,
              fontSize: 12,
              fontFamily: 'Poppins-Regular'
            }}
          >
            {this.state.mapAddress}
          </Text>
        
        </View>
      </View>
    );
  }

here I have doubt where to set these two function properly

this.onRegionChange(region);
 this.getAutoDetectAddress(region.latitude, region.longitude);

maybe if these two functions but I am not sure. Where to implement correctly for getting the best performance.

Upvotes: 0

Views: 1391

Answers (1)

Raikumar Khangembam
Raikumar Khangembam

Reputation: 1008

Map glitches or bouncing (While pinching/zooming in and out) issue were caused by using region={this.state.region}

So, I used initialRegion={this.state.region} instead of region

Here is the complete example

  onChangeValue = region => {
    this.setState({
      region
    });
    Geocoder.from(region.latitude, region.longitude)
      .then(json => {
        this.setState({
          mapAddress: json.results[0].formatted_address,
          mapArea: json.results[0].address_components[1].short_name
        });

        let region = {
          latitude: json.results[0].geometry.location.lat,
          longitude: json.results[0].geometry.location.lng,
          latitudeDelta: 0.021,
          longitudeDelta: 0.021,
          setMapAddress: json.results[0].formatted_address,
          setMapArea: json.results[0].address_components[1].short_name
        };

        this.setState({
          setGeoMarker: region
        });
        // this.map.animateToRegion(region);
      })
      .catch(error => console.warn(error));
  };

...

 <MapView
            style={{
              flex: 1,
              height: Dimensions.get('screen').height / 1.5,

              position: 'relative',
              marginBottom: this.state.marginBottom
            }}
            showsUserLocation={true}
            initialRegion={this.state.region}
            // region={this.state.region}
            showsMyLocationButton={true}
            onRegionChangeComplete={this.onChangeValue}
            ref={ref => (this.map = ref)}
          />
          <View
            style={{
              flex: 1,
              flexDirection: 'row',
              alignItems: 'center',
              position: 'absolute',
              top: '4%',
              left: '-3%'
            }}
          >
            <TouchableOpacity
              onPress={() => {
                {
                  this.props.navigation.navigate('MainTabScreen');
                  this.props.navigation.navigate('HomeScreen');
                }
              }}
            >
              {/*<Icon.MaterialIcons name="arrow-back" size={28} color="black" />*/}
              <Image
                style={{ width: 71, height: 51 }}
                source={require('../../assets/app/mapback.png')}
              />
            </TouchableOpacity>
          </View>
...

Upvotes: 1

Related Questions