@mcmhomes/panorama-viewer
Version:
Provides React components to render panoramas.
67 lines (49 loc) • 2.16 kB
JSX
import React from 'react';
import {PanoramaRenderingLayerSphere} from './PanoramaRenderingLayerSphere.jsx';
import {memo, useEffect, useFadeoutAnimation, useRef, useState} from '../utils/PanoramaUtilsReact.jsx';
import {each, mapToArray, uniqueId} from '../utils/PanoramaUtils.jsx';
const FADEOUT_DELAY_MS = 200;
const FADEOUT_DURATION_MS = 800;
const FADEOUT_DURATION_DECAY_FACTOR = Math.pow(0.01, 1 / (FADEOUT_DURATION_MS / 1000));
const FADEOUT_DURATION_LINEAR = false;
export const PanoramaRenderingLayerMinimumLoadTime = FADEOUT_DELAY_MS;
export const PanoramaRenderingLayerFullFadeTimeMs = FADEOUT_DURATION_MS + 200;
export const PanoramaRenderingLayer = memo(({src, visible, renderOrder}) =>
{
const [renderId, setRenderId] = useState(uniqueId());
const resolutionsRef = useRef([]);
useEffect(() =>
{
if(!visible)
{
return;
}
return src.addListener({
onDone:
({textures, maskTextures}) =>
{
const fadeoutDuration = (FADEOUT_DURATION_LINEAR ? FADEOUT_DURATION_MS : null);
const fadeoutDecayFactor = (FADEOUT_DURATION_LINEAR ? null : FADEOUT_DURATION_DECAY_FACTOR);
each(resolutionsRef.current, resolution => resolution.visible = false);
resolutionsRef.current.unshift({visible:true, key:uniqueId(), props:{textures, maskTextures, fadeoutDuration, fadeoutDecayFactor}});
setRenderId(uniqueId());
},
}).remove;
}, [src, visible]);
return (<>
{mapToArray(resolutionsRef.current, (resolution, index) => (
<PanoramaRenderingLayerResolution {...resolution.props} visible={visible && resolution.visible} renderOrder={renderOrder + (index / resolutionsRef.current.length)} key={resolution.key}/>
))}
</>);
});
const PanoramaRenderingLayerResolution = memo(({src, visible, fadeoutDuration, fadeoutDecayFactor, renderOrder, textures, maskTextures}) =>
{
const {opacity} = useFadeoutAnimation({visible, duration:fadeoutDuration, decayFactor:fadeoutDecayFactor});
if(opacity <= 0)
{
return null;
}
return (<>
<PanoramaRenderingLayerSphere renderOrder={renderOrder} opacity={opacity} radius={1000} textures={textures} maskTextures={maskTextures}/>
</>);
});