maps icon indicating copy to clipboard operation
maps copied to clipboard

[Bug]: getVisibleBounds return wrong coordinate when rotating

Open TheUncharted opened this issue 1 year ago • 2 comments

Mapbox Implementation

Mapbox

Mapbox Version

default

Platform

iOS

@rnmapbox/maps version

10.1.5

Standalone component to reproduce

import { BBox } from 'geojson';
import React, { useRef, useState } from 'react';
import { StyleSheet } from 'react-native';

import Mapbox, { MapView, ShapeSource, UserLocation } from '@rnmapbox/maps';

void Mapbox.setAccessToken("MAPBOX_API_KEY");

const TestMapScreen = () => {
  const [bounds, setBounds] = useState<BBox>();
  const [userLocation, setUserLocation] = useState<Location>();
  const map = useRef<MapView>(null);

  const renderBounds = () => {
    const [westLng, southLat, eastLng, northLat] = bounds;

    const rectangleCoordinates = [
      [westLng, northLat],
      [eastLng, northLat],
      [eastLng, southLat],
      [westLng, southLat],
      [westLng, northLat],
    ];

    return (
      <ShapeSource
        id="boundsSource"
        shape={{
          type: "Feature",
          geometry: {
            type: "Polygon",
            coordinates: [rectangleCoordinates],
          },
          properties: {},
        }}
      >
        <Mapbox.FillLayer
          id="boundsFill"
          style={{
            fillOpacity: 0.2,
            fillColor: "blue",
          }}
        />
      </ShapeSource>
    );
  };

  const onMapIdle = async (event: Mapbox.MapState) => {
    const bounds = await map.current?.getVisibleBounds();

    if (!bounds) {
      return;
    }

    const westLng = bounds[1][0];
    const southLat = bounds[1][1];
    const eastLng = bounds[0][0];
    const northLat = bounds[0][1];
    setBounds([westLng, southLat, eastLng, northLat]);
  };

  return (
    <>
      <Mapbox.MapView
        ref={map}
        scaleBarEnabled={true}
        style={styles.map}
        logoEnabled={false}
        onMapIdle={onMapIdle}
      >
        {bounds && renderBounds()}

        {userLocation && (
          <Mapbox.Camera
            defaultSettings={{
              zoomLevel: 14,
              centerCoordinate: [userLocation.longitude, userLocation.latitude],
            }}
          />
        )}

        <UserLocation
          onUpdate={(newLocation) =>
            setUserLocation({
              latitude: newLocation.coords.latitude,
              longitude: newLocation.coords.longitude,
            })
          }
          showsUserHeadingIndicator={true}
        />
      </Mapbox.MapView>
    </>
  );
};

const styles = StyleSheet.create({
  map: {
    flex: 1,
  },
});

export default TestMapScreen;

Observed behavior and steps to reproduce

When I move the map horizontally or vertically the coordinates of the visible bound box are correct but as soon as I rotate the map the box is skewed and does not reflect the screen

Expected behavior

I expect that getVisibleBounds returns the coordinate of a rectangle matching the mobile screen even after rotating the map

Notes / preliminary analysis

No response

Additional links and references

No response

TheUncharted avatar Jan 14 '24 18:01 TheUncharted

https://github.com/rnmapbox/maps/assets/24917492/d46761bb-dff2-4b0b-93e0-3f847061b7ad

TheUncharted avatar Jan 14 '24 18:01 TheUncharted

@TheUncharted thanks much for the report the example is very clear. Note that getVisibleBounds returns a lat/lng aligned rect so if you rotate the map, by design it can't be a perfect fit. Not really sure what's the use case but you can use getCoordinateFromView to get coordinates for each corner of the map, then you can create the rect/polygon mostly fit's your use case.

https://docs.mapbox.com/ios/maps/api/11.1.0/documentation/mapboxmaps/mapboxmap/coordinatebounds(for:)-54bmw

I'm closing this as for me, as it's not clear to me what this function should return for rotated maps. So it's hard to argue that what's it's returning is wrong.

mfazekas avatar Mar 03 '24 07:03 mfazekas

In my use case, I try to retrieve the bounds to pass it to supercluster : it works quite well except when you rotate the map so for now i disabled the rotation

TheUncharted avatar Mar 03 '24 10:03 TheUncharted