Skip to content

feat: add native onCameraChanged throttling to MapView - #4193

Closed
ciospettw wants to merge 1 commit into
rnmapbox:mainfrom
ciospettw:feat/camera-changed-throttle
Closed

ciospettw wants to merge 1 commit into
rnmapbox:mainfrom
ciospettw:feat/camera-changed-throttle

Conversation

@ciospettw

@ciospettw ciospettw commented Apr 3, 2026 •

Copy link
Copy Markdown

Description

Fixes #4192

Added cameraChangedThrottleInterval to MapView so apps can opt into native throttling for onCameraChanged during gesture-heavy interactions.

The default remains 0, so existing behavior is unchanged unless the new prop is explicitly set.

This PR also updates the Map Handlers example and synchronizes the related docs so the new prop is discoverable and easy to validate.

Checklist

  • I've read CONTRIBUTING.md
  • I updated the doc/other generated code with running yarn generate in the root folder
  • I have tested the new feature on /example app.
    • In V11 mode/ios
    • In New Architecture mode/ios
    • In V11 mode/android
    • In New Architecture mode/android
  • I added/updated a sample - if a new feature was implemented (/example)

Screenshot OR Video

Not included.

Component to reproduce the issue you're fixing

<MapView
  cameraChangedThrottleInterval={250}
  onCameraChanged={(state) => {
    // Throttled intermediate camera updates.
  }}
  onMapIdle={(state) => {
    // Final settled camera state.
  }}
/>

Notes

  • cameraChangedThrottleInterval is fully opt-in and defaults to 0, so omitting it preserves the current event behavior.
  • I manually synchronized docs/MapView.md and docs/examples.json in this checkout.
  • I left the yarn generate checklist item unchecked because node .yarn/releases/yarn-3.6.1.cjs generate currently fails locally in this environment with TypeError: Yallist is not a constructor from hosted-git-info on Node 22.
  • Targeted validation completed: jest __tests__/components/MapView.test.js passes.

@krisgerhard

Copy link
Copy Markdown
Contributor

We incorporated this as a patch and find it very useful. Thank you!

@mfazekas

Copy link
Copy Markdown
Contributor

Thanks a lot for this, @ciospettw, and sorry for the long wait.

We dug into the pinch-zoom lag and found the main cause elsewhere: on Android every MarkerView reported its position to JS and re-rendered on every frame. #4359 removes that round-trip. In our measurements, janky frames while panning went from about 94% to about 50% with 500 markers, and from about 57% to about 12% with 200.

So I'm closing this for now rather than adding a throttle on top. Once #4359 lands, could you re-measure your case on it? If camera-change events are still a measurable bottleneck, we'll happily reconsider a native throttle. I'll keep #4192 open for that.

@mfazekas mfazekas closed this Oct 15, 2026
mfazekas added a commit that referenced this pull request Oct 19, 2026
…ead of echoing it through JS (#4359)

Mapbox positions marker views natively (translationX/Y on Android, the
annotation view's frame on iOS), which the shadow tree doesn't see, so
measure()/measureInWindow() returned the Yoga position and Pressable cancelled
presses as soon as the finger moved (#3832). #4176 fixed this on Android by
sending every position change to JS and re-rendering a matching transform,
which costs a React render per marker per frame while the map moves (#4193).

RNMBXMarkerViewContent now has a custom C++ shadow node whose getTransform()
adds a per-marker offset read from a native side table
(RNMBXMarkerViewContentTranslations). Android writes it through JNI when
Mapbox sets translationX/Y, iOS from the annotation frame. Nothing is
committed while the map moves, and measure is current without a touch, which
also fixes move-taps and measureInWindow on iOS.

The spec stays interfaceOnly; react-native.config.js registers the custom
component descriptor and points autolinking at android/src/main/jni, and the
podspec compiles cpp/ on iOS.

Fixes #4193

This branch had an error being deployed

1 failed deployment
CI with Mapbox Tokens — 58e74e59 Deployed Apr 3, 2026 by ciospettw via CI requiring tokens / Web/Mapbox / Example Build for Web #1056
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: dense onCameraChanged traffic during gestures can overwhelm JS without a native throttle

3 participants