UNPKG

@react-three/uikit

Version:

Build performant 3D user interfaces with react-three-fiber and yoga.

50 lines (49 loc) 1.89 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { forwardRef, useEffect } from 'react'; import { Image } from './image.js'; import { useLoader } from '@react-three/fiber'; import { SRGBColorSpace, TextureLoader } from 'three'; import { Video } from './video.js'; import { suspend } from 'suspend-react'; import { updateVideoElement } from '@pmndrs/uikit/internals'; /** * be aware that this component does not dispose the loaded texture */ export const SuspendingImage = forwardRef(({ src, ...props }, ref) => { const texture = useLoader(TextureLoader, src); texture.colorSpace = SRGBColorSpace; texture.matrixAutoUpdate = false; return _jsx(Image, { ref: ref, src: texture, ...props }); }); const loadVideoElementSymbol = Symbol('load-video-element'); export const SuspendingVideo = forwardRef((props, ref) => { const element = suspend(loadVideoElement, [loadVideoElementSymbol]); updateVideoElement(element, props); useEffect(() => { // Need to append the element to the document, so auto play works. document.body.appendChild(element); return () => element.remove(); }, [element]); return _jsx(Video, { ref: ref, ...props, src: element }); }); function loadVideoElement() { const result = document.createElement('video'); result.style.position = 'absolute'; result.style.width = '1px'; result.style.zIndex = '-1000'; result.style.top = '0px'; result.style.left = '0px'; return new Promise((resolve) => { const handleLoadedData = () => { result.removeEventListener('loadeddata', handleLoadedData); resolve(result); }; // Check if the video already has data loaded if (result.readyState >= 2) { resolve(result); } else { result.addEventListener('loadeddata', handleLoadedData); } }); }