mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
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.
204 lines
5.3 KiB
JavaScript
204 lines
5.3 KiB
JavaScript
import { select as d3_select } from 'd3-selection';
|
|
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
|
import { utilRebind } from '../util';
|
|
|
|
|
|
const pannellumViewerCSS = 'pannellum/pannellum.css';
|
|
const pannellumViewerJS = 'pannellum/pannellum.js';
|
|
const dispatch = d3_dispatch('viewerChanged');
|
|
|
|
let _currScenes = [];
|
|
let _pannellumViewer;
|
|
let _activeSceneKey;
|
|
|
|
export default {
|
|
|
|
init: async function(context, selection) {
|
|
|
|
selection
|
|
.append('div')
|
|
.attr('class', 'photo-frame pannellum-frame')
|
|
.attr('id', 'ideditor-pannellum-viewer')
|
|
.classed('hide', true)
|
|
.on('mousedown', function(e) { e.stopPropagation(); });
|
|
|
|
if (!window.pannellum) {
|
|
await this.loadPannellum(context);
|
|
}
|
|
|
|
const options = {
|
|
'default': { firstScene: '' },
|
|
scenes: {},
|
|
minHfov: 20,
|
|
disableKeyboardCtrl: true,
|
|
sceneFadeDuration: 0
|
|
};
|
|
|
|
_pannellumViewer = window.pannellum.viewer('ideditor-pannellum-viewer', options);
|
|
|
|
_pannellumViewer
|
|
.on('mousedown', () => {
|
|
d3_select(window)
|
|
.on('pointermove.pannellum mousemove.pannellum', () => {
|
|
dispatch.call('viewerChanged');
|
|
});
|
|
})
|
|
.on('mouseup', () => {
|
|
d3_select(window)
|
|
.on('pointermove.pannellum mousemove.pannellum', null);
|
|
})
|
|
.on('animatefinished', () => {
|
|
dispatch.call('viewerChanged');
|
|
});
|
|
|
|
context.ui().photoviewer.on('resize.pannellum', () => {
|
|
_pannellumViewer.resize();
|
|
});
|
|
|
|
this.event = utilRebind(this, dispatch, 'on');
|
|
|
|
return this;
|
|
},
|
|
|
|
loadPannellum: function(context) {
|
|
const head = d3_select('head');
|
|
|
|
return Promise.all([
|
|
new Promise((resolve, reject) => {
|
|
// load pannellum viewer css
|
|
head
|
|
.selectAll('#ideditor-pannellum-viewercss')
|
|
.data([0])
|
|
.enter()
|
|
.append('link')
|
|
.attr('id', 'ideditor-pannellum-viewercss')
|
|
.attr('rel', 'stylesheet')
|
|
.attr('crossorigin', 'anonymous')
|
|
.attr('href', context.asset(pannellumViewerCSS))
|
|
.on('load.pannellum', resolve)
|
|
.on('error.pannellum', reject);
|
|
}),
|
|
new Promise((resolve, reject) => {
|
|
// load pannellum viewer js
|
|
head
|
|
.selectAll('#ideditor-pannellum-viewerjs')
|
|
.data([0])
|
|
.enter()
|
|
.append('script')
|
|
.attr('id', 'ideditor-pannellum-viewerjs')
|
|
.attr('crossorigin', 'anonymous')
|
|
.attr('src', context.asset(pannellumViewerJS))
|
|
.on('load.pannellum', resolve)
|
|
.on('error.pannellum', reject);
|
|
})
|
|
]);
|
|
},
|
|
|
|
/**
|
|
* Shows the photo frame if hidden
|
|
* @param {*} context the HTML wrap of the frame
|
|
*/
|
|
showPhotoFrame: function(context) {
|
|
const isHidden = context.selectAll('.photo-frame.pannellum-frame.hide').size();
|
|
|
|
if (isHidden) {
|
|
context
|
|
.selectAll('.photo-frame:not(.pannellum-frame)')
|
|
.classed('hide', true);
|
|
|
|
context
|
|
.selectAll('.photo-frame.pannellum-frame')
|
|
.classed('hide', false);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Hides the photo frame if shown
|
|
* @param {*} context the HTML wrap of the frame
|
|
*/
|
|
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 = _activeSceneKey = data.image_path;
|
|
if (!_currScenes.includes(key)) {
|
|
let newSceneOptions = {
|
|
showFullscreenCtrl: false,
|
|
autoLoad: false,
|
|
compass: false,
|
|
yaw: 0,
|
|
type: 'equirectangular',
|
|
preview: data.preview_path,
|
|
panorama: data.image_path,
|
|
northOffset: data.ca
|
|
};
|
|
|
|
_currScenes.push(key);
|
|
_pannellumViewer.addScene(key, newSceneOptions);
|
|
}
|
|
|
|
let yaw = 0;
|
|
let pitch = 0;
|
|
let hfov = 0;
|
|
|
|
if (keepOrientation) {
|
|
yaw = this.getYaw();
|
|
pitch = this.getPitch();
|
|
hfov = this.getHfov();
|
|
}
|
|
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();
|
|
_pannellumViewer.removeScene(old_key);
|
|
}
|
|
|
|
_pannellumViewer.resize();
|
|
|
|
return this;
|
|
},
|
|
|
|
getYaw: function() {
|
|
return _pannellumViewer.getYaw();
|
|
},
|
|
|
|
getPitch: function() {
|
|
return _pannellumViewer.getPitch();
|
|
},
|
|
|
|
getHfov: function() {
|
|
return _pannellumViewer.getHfov();
|
|
}
|
|
|
|
};
|