maps icon indicating copy to clipboard operation
maps copied to clipboard

[Bug]: Android Compass never renders when `compassEnabled` & `compassFadeWhenNorth` initially set

Open KiwiKilian opened this issue 2 years ago • 7 comments

Mapbox Implementation

Mapbox

Mapbox Version

default

Platform

Android

@rnmapbox/maps version

#main (10.0.7-rc.0)

Standalone component to reproduce

import { Camera, MapView } from '@rnmapbox/maps';
import React from 'react';

const styles = {
  mapView: { flex: 1 },
};

const BugReportExample = () => {
  return (
    <>
      <MapView style={styles.mapView} compassEnabled compassFadeWhenNorth>
        <Camera
          defaultSettings={{
            centerCoordinate: [-74.00597, 40.71427],
            zoomLevel: 14,
          }}
        />
      </MapView>
    </>
  );
};

export default BugReportExample;

Observed behavior and steps to reproduce

When compassEnabled and compassFadeWhenNorth are initially enabled, the compass is not rendered when rotating the map. It seems to be different, when the prop is enabled after initial rendering, see Ornaments example for comparison.

Expected behavior

The compass should appear, when rotating the map.

Notes / preliminary analysis

Maybe related to #2543.

Additional links and references

No response

KiwiKilian avatar May 19 '23 11:05 KiwiKilian

Our current workaround is:

const BugReportExample = () => {
  const [loaded, setLoaded] = useState(false);

  return (
    <MapView
      style={styles.mapView}
      compassEnabled
      compassFadeWhenNorth={loaded}
      onDidFinishLoadingMap={() => setLoaded(true)}
    >
      <Camera
        defaultSettings={{
          centerCoordinate: [-74.00597, 40.71427],
          zoomLevel: 14,
        }}
      />
    </MapView>
  );
};

KiwiKilian avatar May 30 '23 11:05 KiwiKilian

I tested v10.0.12 on Android and the issue is still present. Can this be fixed?

andrei-tofan avatar Aug 28 '23 11:08 andrei-tofan

Issue still persists, currently this is how I made a workaround:

const [isCompassVisible, setCompassVisible] = useState(false);
...
...

const handleMapLoad = e => {
    setCompassVisible(true);
  };

<MapView
   ...
   ...
   ...
   compassEnabled={isCompassVisible}
   onDidFinishLoadingMap={handleMapLoad}>

Didn't try it together with compassFadeWhenNorth. Currently, this solution works all the time.

ChimiChumi avatar Mar 12 '24 00:03 ChimiChumi

You could also just create your own compass button. That way you can customize the way it looks. E.g.

interface CompassButtonProps {
  mapState: MapState | undefined;
  cameraRef: React.MutableRefObject<Camera | null>;
}

const CompassButton: React.FC<CompassButtonProps> = ({
  cameraRef,
  mapState,
}) => {
  const onCompassPress = () => {
    cameraRef.current?.setCamera({
      heading: 0, // reset camera heading
      animationDuration: 200,
    });
  };

  if (!mapState || !mapState.properties.heading) {
    return null; // disappears when heading is 0
  }

  return (
    <Pressable
      onPress={onCompassPress}
      style={{
        transform: [
          {
            rotate: `${-mapState.properties.heading}deg`,
          },
        ],
      }}
    >
      <Icon name={'compass'} size={30} />
    </Pressable>
  );
};

mapState comes from the onCameraChanged MapView callback


const handleOnCameraChanged = (mapState: MapState) => {
    setMapState(mapState);
  };

<MapView
  onCameraChanged={handleOnCameraChanged}
>
...
</MapView>

brien-crean avatar Jul 12 '24 05:07 brien-crean