-
-
Notifications
You must be signed in to change notification settings - Fork 936
[Bug]: dense onCameraChanged traffic during gestures can overwhelm JS without a native throttle #4192
Copy link
Copy link
Open
Description
Mapbox Version
11.20.1
React Native Version
0.83.2
Platform
- iOS
- Android
@rnmapbox/maps version
10.3.0
Standalone component to reproduce
import React, { useMemo, useState } from 'react';
import { Camera, CircleLayer, MapView, ShapeSource } from '@rnmapbox/maps';
function buildPoints(count) {
return {
type: 'FeatureCollection',
features: Array.from({ length: count }, (_, index) => {
const row = Math.floor(index / 100);
const column = index % 100;
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [12.2 + column * 0.01, 41.6 + row * 0.01],
},
properties: { id: String(index) },
};
}),
};
}
export default function BugReportExample() {
const [cameraChangedCount, setCameraChangedCount] = useState(0);
const [mapIdleCount, setMapIdleCount] = useState(0);
const shape = useMemo(() => buildPoints(5000), []);
return (
<MapView
style={{ flex: 1 }}
onCameraChanged={() => {
setCameraChangedCount((count) => count + 1);
}}
onMapIdle={() => {
setMapIdleCount((count) => count + 1);
}}
>
<Camera centerCoordinate={[12.4964, 41.9028]} zoomLevel={7} />
<ShapeSource id="dense-points" shape={shape}>
<CircleLayer
id="dense-point-layer"
style={{
circleRadius: 3,
circleColor: '#ff4d4d',
}}
/>
</ShapeSource>
</MapView>
);
}Observed behavior and steps to reproduce
- Render a map with a dense source and attach non-trivial JS work to
onCameraChanged. - Pinch-zoom repeatedly.
onCameraChangedfires on every native camera tick on both platforms.- Even if the heavy work is app-side, there is currently no native throttle for this event, so gesture-driven zoom can overwhelm the JS thread faster than
onMapIdlecan settle.
In practice this shows up as zoom stutter in apps that recompute visible data, declutter symbols, or trigger viewport-based fetches during camera changes.
Expected behavior
There should be an opt-in way to reduce onCameraChanged event volume natively while keeping the default behavior unchanged for existing consumers.
A cameraChangedThrottleInterval prop on MapView would let apps trade off intermediate camera granularity against JS load, while still using onMapIdle for the final settled camera state.
Notes / preliminary analysis
- This is not a request to change the default event semantics.
- The change is backward compatible if the prop defaults to
0and preserves current behavior when omitted. - The API shape is consistent with the existing debounce/timing-related
MapViewprops. - A small patch that adds
cameraChangedThrottleInterval?: numberon the JS side and throttles nativecameraChangeddispatch on Android and iOS appears sufficient.
Additional links and references
- A PR with an opt-in implementation and example update will be linked from this issue.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels