From 3c9d232d417cfa3f82519b2363ee90cda7f47b17 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 21 May 2025 16:35:19 +0200 Subject: [PATCH] make sure pannellum viewer is ready to load new photo, fixes #11054 while loading a "scene", pannellum cannot load a new panorama scene. This means we have to wait while the viewer is busy loading an existing panorama until we can load a new one. --- CHANGELOG.md | 2 ++ modules/services/pannellum_photo.js | 37 ++++++++++++++++++++++------- modules/services/panoramax.js | 7 +++--- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 593313922..8ee90bffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ _Breaking developer changes, which may affect downstream projects or sites that #### :scissors: Operations #### :camera: Street-Level * Fix Mapilio photo markers from showing up on low zoom levels ([#11014], thanks [@keiffer213] and [@haipq07]) +* Fix wrong 360° panorama from being displayed when navigating quickly between photos ([#11054]) #### :white_check_mark: Validation #### :bug: Bugfixes * Refresh numeric input fields after leaving focus with the value that is stored in the tag ([#11027]) @@ -58,6 +59,7 @@ _Breaking developer changes, which may affect downstream projects or sites that [#10970]: https://github.com/openstreetmap/iD/pull/10970 [#11014]: https://github.com/openstreetmap/iD/pull/11014 [#11027]: https://github.com/openstreetmap/iD/pull/11027 +[#11054]: https://github.com/openstreetmap/iD/issues/1104 [@keiffer213]: https://github.com/keiffer213 [@haipq07]: https://github.com/haipq07 diff --git a/modules/services/pannellum_photo.js b/modules/services/pannellum_photo.js index 3418c0f8f..1c2c15b18 100644 --- a/modules/services/pannellum_photo.js +++ b/modules/services/pannellum_photo.js @@ -9,6 +9,7 @@ const dispatch = d3_dispatch('viewerChanged'); let _currScenes = []; let _pannellumViewer; +let _activeSceneKey; export default { @@ -29,7 +30,8 @@ export default { 'default': { firstScene: '' }, scenes: {}, minHfov: 20, - disableKeyboardCtrl: true + disableKeyboardCtrl: true, + sceneFadeDuration: 0 }; _pannellumViewer = window.pannellum.viewer('ideditor-pannellum-viewer', options); @@ -96,7 +98,7 @@ export default { * Shows the photo frame if hidden * @param {*} context the HTML wrap of the frame */ - showPhotoFrame: function (context) { + showPhotoFrame: function(context) { const isHidden = context.selectAll('.photo-frame.pannellum-frame.hide').size(); if (isHidden) { @@ -116,22 +118,22 @@ export default { * Hides the photo frame if shown * @param {*} context the HTML wrap of the frame */ - hidePhotoFrame: function (viewerContext) { + hidePhotoFrame: function(viewerContext) { viewerContext .select('photo-frame.pannellum-frame') .classed('hide', false); return this; - }, + }, /** * Renders an image inside the frame * @param {*} data the image data, it should contain an image_path attribute, a link to the actual image. * @param {boolean} keepOrientation if true, HFOV, pitch and yaw will be kept between images */ - selectPhoto: function (data, keepOrientation) { - const {key} = data; - if ( !(key in _currScenes) ) { + selectPhoto: function(data, keepOrientation) { + const key = _activeSceneKey = data.image_path; + if (!_currScenes.includes(key)) { let newSceneOptions = { showFullscreenCtrl: false, autoLoad: false, @@ -156,8 +158,25 @@ export default { pitch = this.getPitch(); hfov = this.getHfov(); } - _pannellumViewer.loadScene(key, pitch, yaw, hfov); - dispatch.call('viewerChanged'); + if (_pannellumViewer.isLoaded() !== false) { + _pannellumViewer.loadScene(key, pitch, yaw, hfov); + dispatch.call('viewerChanged'); + } else { + // pannellum is currently loading another scene: wait for it to finish + // loading the previous panorama first + const retry = setInterval(() => { + if (_pannellumViewer.isLoaded() === false) { + // still not done: wait a bit longer + return; + } + if (_activeSceneKey === key) { + // only load scene if no other photo has been selected in the meantime + _pannellumViewer.loadScene(key, pitch, yaw, hfov); + dispatch.call('viewerChanged'); + } + clearInterval(retry); + }, 100); + } if (_currScenes.length > 3) { const old_key = _currScenes.shift(); diff --git a/modules/services/panoramax.js b/modules/services/panoramax.js index 5c30e8e7e..c6081c7f9 100644 --- a/modules/services/panoramax.js +++ b/modules/services/panoramax.js @@ -483,7 +483,7 @@ export default { _isHD = !_isHD; _definition = _isHD ? highDefinition : standardDefinition; that.selectImage(context, d.id) - .showViewer(context); + .showViewer(context); }); label @@ -518,7 +518,7 @@ export default { .attr('href', viewerLink) .text('panoramax.xyz'); - this.getImageData(d.sequence_id, d.id).then(function(data){ + this.getImageData(d.sequence_id, d.id).then(function(data) { _currentScene = { currentImage: null, nextImage: null, @@ -589,11 +589,12 @@ export default { * @param {*} image_id * @returns The fetched image data */ - getImageData: async function(collection_id, image_id){ + getImageData: async function(collection_id, image_id) { const requestUrl = imageDataUrl.replace('{collectionId}', collection_id) .replace('{itemId}', image_id); const response = await fetch(requestUrl, { method: 'GET' }); + if (!response.ok) { throw new Error(response.status + ' ' + response.statusText); }