diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e6effd201..7f76344a3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### 🐞 Bug fixes - _...Add new stuff here..._ +- Fix how padding is applied when using flyTo() with Globe ([#5406](https://github.com/maplibre/maplibre-gl-js/pull/5406)) ## 5.1.0 diff --git a/src/geo/projection/vertical_perspective_camera_helper.ts b/src/geo/projection/vertical_perspective_camera_helper.ts index 65c9295fe1..7d04220954 100644 --- a/src/geo/projection/vertical_perspective_camera_helper.ts +++ b/src/geo/projection/vertical_perspective_camera_helper.ts @@ -329,6 +329,8 @@ export class VerticalPerspectiveCameraHelper implements ICameraHelper { const startCenter = tr.center; const startZoom = tr.zoom; + const startPadding = tr.padding; + const doPadding = !tr.isPaddingEqual(options.padding); // Obtain target center and zoom @@ -341,9 +343,7 @@ export class VerticalPerspectiveCameraHelper implements ICameraHelper { // Compute target center that respects offset by creating a temporary transform and calling its `setLocationAtPoint`. const clonedTr = tr.clone(); clonedTr.setCenter(constrainedCenter); - if (doPadding) { - clonedTr.setPadding(options.padding as PaddingOptions); - } + clonedTr.setZoom(targetZoom); clonedTr.setBearing(options.bearing); const clampedPoint = new Point( @@ -380,6 +380,10 @@ export class VerticalPerspectiveCameraHelper implements ICameraHelper { const easeFunc = (k: number, scale: number, centerFactor: number, _pointAtOffset: Point) => { const interpolatedCenter = interpolateLngLatForGlobe(startCenter, deltaLng, deltaLat, centerFactor); + if (doPadding) { + tr.interpolatePadding(startPadding, options.padding,k); + } + const newCenter = k === 1 ? targetCenter : interpolatedCenter; tr.setCenter(newCenter.wrap()); @@ -451,4 +455,4 @@ export class VerticalPerspectiveCameraHelper implements ICameraHelper { return oldValue; } } -} \ No newline at end of file +} diff --git a/src/ui/camera.test.ts b/src/ui/camera.test.ts index e0e0a21e85..fda70bb4d5 100644 --- a/src/ui/camera.test.ts +++ b/src/ui/camera.test.ts @@ -3168,6 +3168,50 @@ describe('#flyTo globe projection', () => { expect(camera.getBearing()).toBe(90); }); + test('immediately sets padding with duration = 0', () => { + const camera = createCameraGlobe(); + camera.flyTo({center: [100, 0], duration: 0, padding: {left: 100}}); + expect(camera.getPadding()).toEqual({ + bottom: 0, + left: 100, + right: 0, + top: 0, + }); + + }); + + test('smoothly sets given padding with duration > 0', async () => { + const camera = createCameraGlobe(); + const stub = vi.spyOn(browser, 'now'); + const promise = camera.once('moveend'); + + stub.mockImplementation(() => 0); + + camera.flyTo({center: [100, 0], duration: 100, padding: {left: 100}}); + + stub.mockImplementation(() => 100); + camera.simulateFrame(); + + const padding = camera.getPadding(); + + expect(padding.bottom).toBe(0); + expect(padding.left).toBeCloseTo(100, 4); + expect(padding.right).toBe(0); + expect(padding.top).toBe(0); + + stub.mockImplementation(() => 100); + camera.simulateFrame(); + + await promise; + + expect(camera.getPadding()).toEqual({ + bottom: 0, + left: 100, + right: 0, + top: 0, + }); + }); + test('zooms and rotates', () => { const camera = createCameraGlobe(); camera.flyTo({zoom: 3.2, bearing: 90, animate: false});