diff --git a/CHANGELOG.md b/CHANGELOG.md index e2c3853da9..fa82a46fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### 🐞 Bug fixes - _...Add new stuff here..._ +- Render frame synchronized again in requestAnimationFrame callback ([#4535](https://github.com/maplibre/maplibre-gl-js/pull/4535)) ## 5.0.1 diff --git a/src/ui/map.ts b/src/ui/map.ts index 160611fdf6..00e69a45e2 100644 --- a/src/ui/map.ts +++ b/src/ui/map.ts @@ -3379,15 +3379,21 @@ export class Map extends Camera { triggerRepaint() { if (this.style && !this._frameRequest) { this._frameRequest = new AbortController(); - browser.frameAsync(this._frameRequest).then((paintStartTimeStamp: number) => { - PerformanceUtils.frame(paintStartTimeStamp); - this._frameRequest = null; - this._render(paintStartTimeStamp); - }).catch((error: Error) => { - if (!isAbortError(error) && !isFramebufferNotCompleteError(error)) { - throw error; - } - }); + browser.frame( + this._frameRequest, + (paintStartTimeStamp) => { + PerformanceUtils.frame(paintStartTimeStamp); + this._frameRequest = null; + try { + this._render(paintStartTimeStamp); + } catch(error) { + if (!isAbortError(error) && !isFramebufferNotCompleteError(error)) { + throw error; + } + } + }, + () => {} + ); } } diff --git a/src/ui/map_tests/map_events.test.ts b/src/ui/map_tests/map_events.test.ts index 67f0224c52..51109ca9c5 100644 --- a/src/ui/map_tests/map_events.test.ts +++ b/src/ui/map_tests/map_events.test.ts @@ -990,8 +990,9 @@ describe('map events', () => { await sourcePromise; }); - test('getZoom on moveend is the same as after the map end moving, with terrain on', () => { + test('getZoom on moveend is the same as after the map end moving, with terrain on', async () => { const map = createMap({interactive: true, clickTolerance: 4}); + await map.once('style.load'); map.terrain = createTerrain(); let actualZoom: number; map.on('moveend', () => { diff --git a/src/ui/map_tests/map_zoom.test.ts b/src/ui/map_tests/map_zoom.test.ts index 6433d1727f..910f133e54 100644 --- a/src/ui/map_tests/map_zoom.test.ts +++ b/src/ui/map_tests/map_zoom.test.ts @@ -79,12 +79,13 @@ test('throw on maxZoom smaller than minZoom at init with falsey maxZoom', () => }).toThrow(new Error('maxZoom must be greater than or equal to minZoom')); }); -test('recalculate zoom is done on the camera update transform', () => { +test('recalculate zoom is done on the camera update transform', async () => { const map = createMap({ interactive: true, clickTolerance: 4, transformCameraUpdate: ({zoom}) => ({zoom: zoom + 0.1}) }); + await map.once('style.load'); map.terrain = createTerrain(); const canvas = map.getCanvas(); simulate.dragWithMove(canvas, {x: 100, y: 100}, {x: 100, y: 150}); diff --git a/src/util/browser.ts b/src/util/browser.ts index 0f56e0006a..393d36364c 100755 --- a/src/util/browser.ts +++ b/src/util/browser.ts @@ -16,13 +16,17 @@ export const browser = { */ now, + frame(abortController: AbortController, fn: (paintStartTimestamp: number) => void, reject: (error: Error) => void): void { + const frame = requestAnimationFrame(fn); + abortController.signal.addEventListener('abort', () => { + cancelAnimationFrame(frame); + reject(createAbortError()); + }); + }, + frameAsync(abortController: AbortController): Promise { return new Promise((resolve, reject) => { - const frame = requestAnimationFrame(resolve); - abortController.signal.addEventListener('abort', () => { - cancelAnimationFrame(frame); - reject(createAbortError()); - }); + this.frame(abortController, resolve, reject); }); },