[Bug]: Android Compass never renders when `compassEnabled` & `compassFadeWhenNorth` initially set
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
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>
);
};
I tested v10.0.12 on Android and the issue is still present. Can this be fixed?
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.
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>