Skip to content

feat: add focalPoint - #4163

Merged
mfazekas merged 6 commits into
rnmapbox:mainfrom
ted-mundy:feature/focal-point
Nov 9, 2026
Merged

mfazekas merged 6 commits into
rnmapbox:mainfrom
ted-mundy:feature/focal-point

Conversation

@ted-mundy

@ted-mundy ted-mundy commented Feb 27, 2026 •

Copy link
Copy Markdown
Contributor

Description

Added focalPoint into the React Native version of the package. Functionality already exists in both Android and iOS, but no bridge was ever built. This builds that bridge 🙂

The DocJSONBuilder.mjs change expands nested object types in the generated docs, which also changes the padding type shown in Camera.md.

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

See the Map > Gesture Focal Point example and the verification notes in the comments.

@ted-mundy
ted-mundy had a problem deploying to CI with Mapbox Tokens February 27, 2026 16:39 — with GitHub Actions Failure
@ted-mundy
ted-mundy had a problem deploying to CI with Mapbox Tokens February 27, 2026 16:39 — with GitHub Actions Failure
@ted-mundy
ted-mundy had a problem deploying to CI with Mapbox Tokens February 27, 2026 16:39 — with GitHub Actions Failure
…val, add example

Android converts the dp focal point to pixels for GesturesSettings.focalPoint.
Both platforms clear the focal point when it's removed from gestureSettings.
The doc generator now expands nested object types instead of printing
'signature'.
@mfazekas

Copy link
Copy Markdown
Contributor

Thanks @ted-mundy, this is a nice addition! I pushed a commit on top of yours (your commits are unchanged; I merged main in first) to finish it off:

  1. Android: focalPoint is now passed to GesturesSettings.focalPoint, converted from dp to pixels.
  2. Removing focalPoint from gestureSettings now resets it, on both iOS and Android.
  3. Docs: the generator now expands nested object types, so focalPoint shows as {x: number, y: number} instead of signature. Camera's padding was hitting the same issue and is fixed too. The description now says the point is in points/dp, relative to the map view's top-left.
  4. A new Map > Gesture Focal Point example. It draws a marker at the focal point, lets you toggle the focal point, and shows the coordinate under the marker. That coordinate should stay put while you zoom or rotate.

Both SDKs use the focal point for pinch, rotate, double-tap zoom-in and two-finger-tap zoom-out.

Verification: the gestures were run away from the marker, then I checked whether the coordinate under the marker moved.

  • iOS simulator: pinch, rotate and double-tap all kept the coordinate fixed with the focal point on. With it off, all three moved it, and turning it back on restored the pivot.
  • Android emulator (density 2.625): rotate, double-tap and two-finger tap kept the coordinate fixed with the focal point on, which also confirms the dp→px conversion. With it off, double-tap and two-finger tap moved it. Pinch with the focal point on couldn't be driven reliably by injected multi-touch on the emulator (pinch on other examples failed the same way), so that one still needs a check on a real device.

@ted-mundy

Copy link
Copy Markdown
Contributor Author

Am I ok to undraft this @mfazekas ?

@mfazekas mfazekas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this works well. I checked it on the iOS simulator and Android emulator: pinch, double-tap and rotate keep the focal point fixed on both, the dp to px conversion on Android lands in the same spot as iOS, and turning it off via focalPoint: undefined resets it. A couple of things before merging:

  1. Android: removing the whole gestureSettings prop shows a redbox (ClassCastException: Dynamic value from Object is not a ReadableMap). settings.asMap() throws on a null Dynamic instead of returning null, so the map == null reset branch never runs. Checking settings.isNull (or settings.type != ReadableType.Map) before asMap() and clearing focalPoint there should fix it. main crashes the same way, but since this PR makes removal reset the focal point it'd be good to make that work on Android too.
  2. Docs: the iOS SDK ignores focalPoint for pinch while pinchPanEnabled is true, which is the default. Worth one sentence in the focalPoint doc saying to set pinchPanEnabled: false to keep pinch anchored (e.g. under a navigation puck).
  3. Small one: the DocJSONBuilder.mjs change also changes the generated padding types in Camera.md. That's an improvement, just mention it in the PR description so it isn't a surprise.

Optional: RNMBXMapView already has toPx(ScreenCoordinate) for dp to px; making it internal and reusing it would avoid a second copy of the density math in the manager.

# Conflicts:
#	android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt
#	example/src/examples/Map/index.js
…Settings is removed

Also document that iOS pinch ignores focalPoint while pinchPanEnabled is true.
@mfazekas

mfazekas commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Sorry for missing your question, @ted-mundy. Yes, undrafting was fine. We've finished the remaining review items on top of your branch: merged main, fixed the Android redbox when gestureSettings is removed, and documented that iOS pinch ignores the focal point unless pinchPanEnabled is false. We'll merge once CI is green. Thanks for the PR!

@mfazekas mfazekas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review fixes are in; verified on Android.

@mfazekas
mfazekas merged commit 8c3c3dd into rnmapbox:main Nov 9, 2026
19 of 20 checks passed

This branch had an error being deployed

1 failed (outdated) and 1 inactive deployments
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.

2 participants