briantk
briantk

Reputation: 21

react-native-maps initialRegion, region and animateToRegion not working for iOS but working for Android

I have a React Native project using react-native-maps:

    getRegionForCoordinates(points) {
        // points should be an array of { latitude: X, longitude: Y }
        let minX, maxX, minY, maxY;

        var arr = [];
        Object.keys(points).map(key => {
            var point = points[key];
            arr.push([{latitude: point.latitude, longitude: point.longitude}])
        })
        points = arr;

        var first = points[0];
        minX = first[0].latitude;
        maxX = first[0].latitude;
        minY = first[0].longitude;
        maxY = first[0].longitude;

        // calculate rect
        points.map((point) => {
            minX = Math.min(minX, point[0].latitude);
            maxX = Math.max(maxX, point[0].latitude);
            minY = Math.min(minY, point[0].longitude);
            maxY = Math.max(maxY, point[0].longitude);
        });

        const midX   = (minX + maxX) / 2;
        const midY   = (minY + maxY) / 2;
        const deltaX = (maxX - minX);
        const deltaY = (maxY - minY);

        return {
            latitude       : midX,
            longitude      : midY,
            latitudeDelta  : deltaX,
            longitudeDelta : deltaY
        };
    }
   componentDidMount() {
      var event     = this.props.event;
      var mapData   = JSON.parse(event.map);
      var map       = mapData[0];
      var markers = [];
      Object.keys(map.markers).map(key => {
         var marker = map.markers[key];
         var obj = [{ latitude: parseFloat(marker.lat), longitude: parseFloat(marker.lng) }];
         markers.push(obj[0]);
      });
      var region = this.getRegionForCoordinates(markers);


      setTimeout(() => {
         this.ref.animateToRegion(region, 1);
      }, 5000)
   }
    renderMap() {
      var event     = this.props.event;
      var mapData   = JSON.parse(event.map);
      var map       = mapData[0];
        return (
            <View>
                <MapView
                    provider={PROVIDER_GOOGLE}
                    style={mapStyles.map}

               ref={(map) => {
                  this.ref = map
               }}
                    customMapStyle={customMapStyle}

                      key={ `${Date.now()}` }
                    >

                    {
                        map.markers.map(marker => {
                            return (
                                <EventMapMarker marker={marker} navigation={this.props.navigation} />
                            )
                        })
                    }
                </MapView>
            </View>
        )
    }

In this code I am trying to animate to a region based on the markers that will be displayed on the map. The latitude, longitude, latitudeDelta and longitudeDelta are correct as they work for Android.

However, on iOS it animates to a completely wrong region, both in the simulator and on the device.

Setting initialRegion or region doesn't seem to make any difference.

I have tried a bunch of different things, like animating in the onMapReady function, using a setTimeout to delay the animate, updating/downgrading react-native-maps, etc.. I don't know if this is a bug or something I have set incorrectly in my project.

React Native version is 0.59.0.

react-native-maps version is 0.27.1.

Upvotes: 2

Views: 4698

Answers (2)

Max Hay
Max Hay

Reputation: 259

There are several possible causes that I have found so far, depending on the exact nature of how your map is animating to the wrong region.

Centre of target is at the top left of the map.

I am not entirely certain why this one occurs. I just know that manually setting the map's position after a short timeout after it's creation seems to stop it from occurring.

const [mapStyle, setMapStyle] = useState({ height: 0 });
useEffect(() => {
    setTimeout(() => {
        setMapStyle({});
    }, 2000);
}, []);
return <>
    <MapView provider={PROVIDER_GOOGLE}
        style={[StyleSheet.absoluteFillObject, mapStyle]}  ...

My best guess is somewhere along the lines of this:

  • I tell it to align the map to a marker.
  • Because of some reason, a race condition of some form, perhaps, it thinks at this stage the map's height is 0x0.
  • Because of this, it sets the map's position to that marker but with no width or height.
  • Then something happens and it has to scale the map up to meet the actual width and height of the map view, but it anchors to the top left corner, so that's where the centre of the region is shown.

Manually resetting the height/width seems to kick it and stop it from thinking the map's height is 0x0, so it doesn't have the same problem.

For whatever reason, this issue for me was intermittent and also specific to iOS google maps.

Map stays at current position but zoom level is correct

This probably means your latitude delta's too large. Specifying a region that includes any latitude value not between 90.0 or -90.0 seems to prevent the map from animating to that region. Instead it will only set the zoom level, leaving the camera at the current position.

In other words, if abs(latitude) + latitudeDelta / 2 is greater than 90, then you will see this issue.

Animating to 180.0 longitude always

Specifying a longitude delta greater than 180 will cause the map to animate to 180.0 longitude always.

Upvotes: 0

Akshay Adiga
Akshay Adiga

Reputation: 21

It doesn't work if you set provider={PROVIDER_GOOGLE}. Removing that, it works even on IOS. Not sure why. I am facing the same issue.

Use the timing method: https://jakallergis.com/google-maps-in-react-native-part-3-advanced-usage This works for me

Upvotes: 1

Related Questions