[Bug]: "setCamera" with bounds option doesn't fit these bounds (Android)
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 2.9k
- Forks
- 947
- Avg merge
- 6d 37m
- Merged PRs (30d)
- 1
Description
Mapbox Implementation
Mapbox
Mapbox Version
11.15.3
React Native Version
0.82.0
React Native Architecture
New Architecture (Fabric/TurboModules)
Platform
Android
@rnmapbox/maps version
10.2.4
Standalone component to reproduce
import React, { useCallback, useRef, useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { MapView, Camera, MarkerView } from '@rnmapbox/maps';
const point1 = [-122.1, 37];
const point2 = [-121.2, 37];
const BugReportExample = () => {
const camera = useRef(null);
const [mode, setMode] = useState(0);
const setCamera = useCallback(() => {
switch (mode) {
case 0:
camera.current?.setCamera({
bounds: {
ne: point1,
sw: point2,
},
});
setMode(1);
break;
case 1:
camera.current?.setCamera({
centerCoordinate: point1,
zoomLevel: 14,
});
setMode(2);
break;
case 2:
camera.current?.setCamera({
centerCoordinate: point2,
zoomLevel: 14,
});
setMode(0);
break;
}
}, [mode]);
return (
<View style={styles.container}>
<MapView style={styles.map}>
<Camera
ref={camera}
defaultSettings={{ centerCoordinate: point1, zoomLevel: 14 }}
/>
<MarkerView coordinate={point1} allowOverlap>
<View style={[styles.marker, styles.red]} />
</MarkerView>
<MarkerView coordinate={point2} allowOverlap>
<View style={[styles.marker, styles.orange]} />
</MarkerView>
</MapView>
<Pressable style={styles.button} onPress={setCamera}>
<Text style={styles.buttonText}>Switch Camera</Text>
</Pressable>
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
},
map: {
flex: 1,
},
marker: {
width: 20,
height: 20,
borderRadius: 5,
},
red: {
backgroundColor: 'red',
},
orange: {
backgroundColor: 'orange',
},
button: {
position: 'absolute',
top: 40,
right: 20,
paddingVertical: 4,
paddingHorizontal: 12,
borderRadius: 8,
backgroundColor: '#FFF',
},
buttonText: {
fontSize: 14,
fontWeight: 'bold',
color: '#000',
},
});
Observed behavior and steps to reproduce
Switch camera by tapping "Switch Camera"
https://github.com/user-attachments/assets/84bb30ea-8e1d-4e66-8277-c149e3076991
Expected behavior
Red and orange points should fits screen bounds
Notes / preliminary analysis
If you change coordinates to these than camera would be in correct position
const point1 = [-121.1, 37];
const point2 = [-121.1, 37.1];
https://github.com/user-attachments/assets/f6b4ae90-16e0-4b80-a22e-2141ee55f297
There are another issues with "setCamera" with bounds option and paddingBottom have been set to half of the screen or more. But I think the core issue may be the same
Also I have researched native code and it seems that Mapbox SDK 11.15.3 is broken.
Passed correct data to camera options calculations
The center was calculated correctly, but zoom is 0
Issues with padding
The camera is not centered in the acceptable area.
https://github.com/user-attachments/assets/fce93fd5-d09d-4c82-baa7-d04979215516
Standalone component to reproduce
import React, { useCallback, useRef, useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { MapView, Camera, MarkerView } from '@rnmapbox/maps';
const center = [-121.1, 37];
const northPoint = [-121.1, 37.1];
const northWestPoint = [-121.2, 37.1];
const westPoint = [-121.2, 37];
const paddingTop = 40;
const paddingBottom = 300;
const paddingLeft = 40;
const paddingRight = 40;
const BugReportExample = () => {
const camera = useRef(null);
const [mode, setMode] = useState(0);
const setCamera = useCallback(() => {
switch (mode) {
case 0:
camera.current?.setCamera({
bounds: {
ne: center,
sw: northPoint,
},
animationDuration: 300,
animationMode: 'linearTo',
});
setMode(1);
break;
case 1:
camera.current?.setCamera({
bounds: {
ne: center,
sw: northWestPoint,
},
animationDuration: 300,
animationMode: 'linearTo',
});
setMode(2);
break;
case 2:
camera.current?.setCamera({
bounds: {
ne: center,
sw: westPoint,
},
animationDuration: 300,
animationMode: 'linearTo',
});
setMode(3);
break;
case 3:
camera.current?.setCamera({
centerCoordinate: center,
zoomLevel: 10,
animationDuration: 300,
animationMode: 'linearTo',
});
setMode(0);
break;
}
}, [mode]);
return (
<View style={styles.container}>
<MapView style={styles.map}>
<Camera
ref={camera}
defaultSettings={{
centerCoordinate: center,
zoomLevel: 10,
}}
padding={{
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
}}
/>
<MarkerView coordinate={center} allowOverlap>
<View style={[styles.marker, styles.red]} />
</MarkerView>
<MarkerView coordinate={northPoint} allowOverlap>
<View style={[styles.marker, styles.orange]} />
</MarkerView>
<MarkerView coordinate={northWestPoint} allowOverlap>
<View style={[styles.marker, styles.orange]} />
</MarkerView>
<MarkerView coordinate={westPoint} allowOverlap>
<View style={[styles.marker, styles.orange]} />
</MarkerView>
</MapView>
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: paddingTop,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
}}
pointerEvents='none'
/>
<View
style={{
position: 'absolute',
top: paddingTop,
left: 0,
bottom: paddingBottom,
width: paddingLeft,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
}}
pointerEvents='none'
/>
<View
style={{
position: 'absolute',
top: paddingTop,
right: 0,
bottom: paddingBottom,
width: paddingRight,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
}}
pointerEvents='none'
/>
<View
style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
height: paddingBottom,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
}}
pointerEvents='none'
/>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 60,
alignItems: 'center',
}}
>
<Pressable style={styles.button} onPress={setCamera}>
<Text style={styles.buttonText}>Switch Camera</Text>
</Pressable>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
},
map: {
flex: 1,
},
marker: {
width: 20,
height: 20,
borderRadius: 5,
},
red: {
backgroundColor: 'red',
},
orange: {
backgroundColor: 'orange',
},
button: {
paddingVertical: 4,
paddingHorizontal: 12,
borderRadius: 8,
backgroundColor: '#FFF',
},
buttonText: {
fontSize: 16,
fontWeight: 'bold',
color: '#000',
},
});
Additional links and references
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the standalone React Native reproductions and inspect the native camera options calculation described in the report for Mapbox SDK 11.15.3. Check bounds fitting with both coordinate orientations and large bottom padding on Android; done means both points fit the screen and the camera is centered within the padded area.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, javascript, kotlin, react-native
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100