Repository navigation
fix(camera): correct padding and degenerate bounds fitting - #4351
Open
RobJacobson wants to merge 3 commits into
Open
RobJacobson wants to merge 3 commits into
RobJacobson wants to merge 3 commits into
Conversation
- Pass resolved viewport padding through native camera options before fitting bounds - Use zero additional coordinate padding on iOS and Android - Preserve omitted padding edges and explicit or inherited bearing and pitch - Verify the padding reset and related cases against real native SDKs on both platforms
- Expand zero-width or zero-height bounds only for camera fitting. - Preserve exact source bounds for camera constraints. - Add regression tests for thin, point, and boundary bounds.
This was referenced Oct 13, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #4217.
Fixes #4050. This PR also handles camera fitting for point and zero-width/zero-height bounds reported in #4050. Android expands degenerate bounds by a minimal amount only for fitting and keeps exact bounds for constraints; regression tests cover point, thin, and boundary bounds.
After centering with bottom padding 500, fitting bounds with explicit bottom padding 0 retains the old padding. Bounds fitting uses the deprecated native fitting APIs, which treat their padding argument as extra coordinate padding inside the current viewport. The returned camera does not supply replacement viewport padding.
Use the native fitting overload that accepts
CameraOptions, with the resolved viewport padding on that camera and zero additional coordinate padding. This allows explicit zero to clear an edge, keeps existing padding on omitted edges, and preserves explicit or inherited bearing and pitch. Apply the same correction on iOS and Android. The commit contains only the two native camera implementations.Checklist
CONTRIBUTING.mdyarn generatein the root folder/exampleapp./example)Generation completed without generated changes. This is a bug fix; the new-feature sample item is not applicable. The reproducer is included below and kept outside the commit. The full
/exampleapp was built and run on iOS and Android with React Native 0.84.1, Hermes and Fabric. Local-only compatibility settings were needed for the installed Xcode: the supported iOS deployment target, ARM simulator architecture, and a scene delegate. All setup changes and diagnostic code were removed from the checkout after verification.Verification
Full
/exampleapp verificationThe same animated JS reproducer ran in the real example binary with each revision's native camera implementation. It invokes
Camera.setCamerawith 500 ms animations and samples final idle state after 1400 ms. A temporary_issue4217Paddingfield in camera/idle event properties reads the SDK's actual viewport padding. Framing is additionally checked through the publicgetZoom,getCenter, andgetPointInViewmethods. Android expectations account for the existing integer pixel conversion. Temporary diagnostics do not alter camera behavior and are excluded from the commit.Both unfixed builds fail the padding reset, fresh-frame comparison, repeated padding 80, and partial-edge reset checks. Both fixed builds pass all ten checks, including the initial center command, omitted edges, repeated framing, and explicit/inherited bearing and pitch. On iOS, the reset's zoom changes from 14.066 before to 14.787 after, matching the fresh unpadded fit. On Android, it changes from 14.213 before to 14.819 after, also matching the fresh fit.
Captured full example-app assertions
ios before
ios after
android before
android after
Native-only verification
yarn teston the isolated branch: lint completed with no errors (existing warnings), 25 suites and 164 unit tests passed.git diff --checkpassed.Fresh before/after native builds execute the issue's sequence (center with bottom padding 500, then fit bounds with padding 0), plus repeated bounds fitting, partial and omitted padding updates, and explicit/inherited bearing and pitch. iOS builds the exact
RNMBXCamera.toUpdateItemmethod extracted from each revision; Android builds the completeCameraStopclass and the unchanged bounds helper. Minimal harness support applies the resulting camera directly to a real native map, without animation. SDKs: iOS 11.20.3 on iPhone 18 Pro/iOS 27 simulator; Android 11.23.1 on a local emulator. Before uses base commit42758736839a432f50227289d08dedb7617d8aab; after uses commit38f679265dd298eab14d52a40bb980143c9c936b.Before: iOS 5/9 passed; Android 6/9 passed. After: 9/9 passed on each platform.
Captured before/after camera-state and assertion output
ios before
ios after
android before
android after
Screenshot OR Video
Before/after screenshots were captured from both
/examplebinaries. The full camera-state and assertion output is included above; both fixed screens displayRESULT checks=10 failures=0.Component to reproduce the issue you're fixing
Adapted from the component in #4217 and the structure of
BugReportExample.js. It uses local point data and a local style without external tiles or extra libraries. Use it in an app configured for@rnmapbox/maps.On a fresh map, press Baseline and remember the framing. Then press 1 and 2, waiting for each animation to finish. Before the fix, bottom padding remains 500 after step 2; after the fix it becomes 0 and the framing matches Baseline. Press Repeat twice: bottom padding should stay 80 and the second fit should keep the same framing.
Self-contained React Native component