UNPKG

@mcmhomes/panorama-viewer

Version:
160 lines (138 loc) 3.33 kB
/*eslint-disable react-compiler/react-compiler*/ import React from 'react'; import {PanoramaRenderingLayer, PanoramaRenderingLayerFullFadeTimeMs} from './PanoramaRenderingLayer.jsx'; import {each, mapToArray, setAnimationFrameTimeoutRemovable, setTimeoutRemovable, uniqueId} from '../utils/PanoramaUtils.jsx'; import {memo, useEffect, useRef, useState} from '../utils/PanoramaUtilsReact.jsx'; export const PanoramaRendererLayers = memo(({src}) => { const currentLayersRef = useRef([]); const [currentLayers, setCurrentLayers] = useState([]); useEffect(() => { const now = performance.now(); /** create a lookup table **/ let newSrc = {}; each(src, (item, index) => { newSrc[item.basePath] = item; }); /** dispose layers that are not in the new src **/ each(currentLayersRef.current, (layer, index) => { if(!layer.visible) { /** already being disposed **/ return; } if(newSrc[layer.src.basePath]) { /** exists, don't dispose **/ delete newSrc[layer.src.basePath]; return; } /** removed, dispose **/ layer.visible = false; layer.visibleLastTime = now; setTimeoutRemovable(() => { currentLayersRef.current = currentLayersRef.current.filter(item => (item.key !== layer.key)); setCurrentLayers([...currentLayersRef.current]); setAnimationFrameTimeoutRemovable(() => { layer.src.dispose(); }, 10); }, PanoramaRenderingLayerFullFadeTimeMs); }); /** add new layers **/ each(newSrc, (item, basePath) => { currentLayersRef.current.push({key:uniqueId(), time:now, src:item, visible:true}); }); /** sort the layers, in render order **/ /** the one that is fading out, has to be rendered on top (rendered later) **/ const A = -1; // render a first, meaning it will be rendered below B const B = 1; // render b first, meaning it will be rendered below A currentLayersRef.current.sort((a, b) => { if((a.src.styleIndex !== b.src.styleIndex) || (a.src.locationIndex !== b.src.locationIndex)) { if(!a.visible && !b.visible) { if(a.visibleLastTime > b.visibleLastTime) { return A; } if(a.visibleLastTime < b.visibleLastTime) { return B; } } else { if(!a.visible) { return B; } if(!b.visible) { return A; } } if(a.time > b.time) { return A; } if(a.time < b.time) { return B; } return 0; } if(a.src.layerRenderOrder < b.src.layerRenderOrder) { return A; } if(a.src.layerRenderOrder > b.src.layerRenderOrder) { return B; } if(!a.visible && !b.visible) { if(a.visibleLastTime > b.visibleLastTime) { return A; } if(a.visibleLastTime < b.visibleLastTime) { return B; } } else { if(!a.visible) { return B; } if(!b.visible) { return A; } } if(a.time > b.time) { return A; } if(a.time < b.time) { return B; } return 0; }); setCurrentLayers([...currentLayersRef.current]); }, [src]); return (<> {mapToArray(currentLayers, (layer, index) => ( <PanoramaRenderingLayer key={layer.key} src={layer.src} visible={layer.visible} renderOrder={index}/> ))} </>); });