let slideShowInterval = null /** * Disables hiding of various child items * once model has loaded */ modelLoaded = function(e) { $('.awaiting-model').css('display', 'flex').removeClass('awaiting-model') if (typeof enableMenu != 'undefined') {enableMenu()} } /** * Event listener callback to toggle the visibility * of a hotspot's annotation when the hotspot is * clicked * * @param {PointerEvent} e */ onAnnotation = function(e) { e.stopPropagation() if (typeof isDeleting != 'undefined' && isDeleting()) { clickDeleteHotspot(e) return } let targetAnnotation = Number.parseInt(e.target.slot.split('-')[1]) let targetModel = e.target.closest('model-viewer') selectAnnotation(targetModel, targetAnnotation) } /** * Event listener callback to hide all hotspot * annotations when the model-viewer receives * a click event */ clearAnnotations = function() { [...document.getElementsByClassName('HotspotAnnotation')].forEach( an => { an.classList.add('HiddenAnnotation') }) }; /** * Select the numbered hotspot of the given model * * @param {ModelViewer} mView * @param {number} annotId * * @return {bool} true if annotation selected false if unselected */ selectAnnotation = function(mView, annotId) { let anSelected = false; [...mView.querySelectorAll('.HotspotAnnotation')].forEach( (an, idx) => { if (idx + 1 == annotId && an.classList.contains('HiddenAnnotation')) { an.classList.remove('HiddenAnnotation'); if (an.parentElement.dataset.target) {mView.cameraTarget = an.parentElement.dataset.target} if (an.parentElement.dataset.orbit) {mView.cameraOrbit = an.parentElement.dataset.orbit} const anFov = an.parentElement.getAttribute('field-of-view') if (anFov) {mView.fieldOfView = anFov} anSelected = true } else { an.classList.add('HiddenAnnotation'); } }); return anSelected } /** * Select the next numbered hotspot * * @param {ModelViewer} mView * * @return {number} ID number of the newly selected hotspot */ nextAnnotation = function(mView) { let incrAnnotation = 0 const numSpots = [...mView.querySelectorAll('Button:not([seq-skip])')].length const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0] if (!currentAnnotation) { incrAnnotation = 1 } else { const annotationId = Number.parseInt(currentAnnotation.slot.split('-')[1]) incrAnnotation = (annotationId >= numSpots) ? 1 : annotationId + 1 } selectAnnotation(mView, incrAnnotation) return incrAnnotation } /** * Select the previous numbered hotspot * * @param {ModelViewer} mView * * @return {number} ID number of the newly selected hotspot */ prevAnnotation = function(mView) { let decrAnnotation = 0 const numSpots = [...mView.querySelectorAll('Button:not([seq-skip])')].length const currentAnnotation = mView.querySelectorAll('Button:has(.HotspotAnnotation:not(.HiddenAnnotation))')[0] if (!currentAnnotation) { decrAnnotation = numSpots } else { const annotationId = Number.parseInt(currentAnnotation.slot.split('-')[1]) decrAnnotation = (annotationId <= 1) ? numSpots : annotationId - 1 } selectAnnotation(mView, decrAnnotation) return decrAnnotation } /** * Cycle through the available annotations * * @param {ModelViewer} mView * * @param {Number} [slideDuration = 5000] * * @return {intervalID} ID of the created interval timer */ slideshowAnnotations = function(mView, slideDuration = 3000) { if (slideShowInterval) { clearInterval(slideShowInterval) } else { nextAnnotation(mView) slideShowInterval = setInterval(nextAnnotation, slideDuration, mView) } } /** * Toggle visibility of all annotations * * @param {ModelViewer} mView */ toggleAnnotations = function(mView) { if (slideShowInterval) { clearInterval(slideShowInterval) const slideButton = mView.parentElement.querySelector('[toggled]') if (slideButton) slideButton.toggleAttribute('toggled') } [...mView.querySelectorAll('button')].forEach( hs => { hs.toggleAttribute('hidden') }) const hsButtons = [...mView.parentElement.querySelectorAll('.disable-on-hide')] hsButtons.forEach( mb => { mb.toggleAttribute('disabled') }) } /** * Respond to full screen changes on the gl container * * @param {Element} glCont container element to enlarge or reduce */ toggleFullScreen = function(glCont) { if (document.fullscreenElement) { document.exitFullscreen() } else { glCont.requestFullscreen() } } /** * Reset view to initial position * * @param {ModelViewer} mView */ resetView = function(mView) { const resetOrb = mView.getAttribute('camera-orbit') || 'auto auto auto' const resetTarg = mView.getAttribute('camera-target') || 'auto auto auto' const resetFov = mView.getAttribute('field-of-view') || 'auto' mView.cameraOrbit = resetOrb mView.cameraTarget = resetTarg mView.fieldOfView = resetFov }