UNPKG

@pmndrs/uikit

Version:

Build performant 3D user interfaces with Three.js and yoga.

52 lines (51 loc) 1.95 kB
import { Image } from './image.js'; import { VideoTexture } from 'three'; import { effect, signal } from '@preact/signals-core'; import { setupVideoElementInvalidation, updateVideoElement, } from '../components/index.js'; export class Video extends Image { element; texture; aspectRatio; updateAspectRatio; unsubscribeInvalidate; constructor(props, defaultProperties) { const element = props.src instanceof HTMLVideoElement ? props.src : document.createElement('video'); if (!(props.src instanceof HTMLVideoElement)) { updateVideoElement(element, props); } const texture = new VideoTexture(element); texture.needsUpdate = true; const aspectRatio = signal(1); super({ aspectRatio, ...props, src: texture }, defaultProperties); this.unsubscribeInvalidate = effect(() => { const root = this.parentContextSignal.value?.value?.root; if (root == null) { return; } return setupVideoElementInvalidation(element, root.requestRender); }); this.element = element; this.texture = texture; this.aspectRatio = aspectRatio; this.updateAspectRatio = () => (aspectRatio.value = this.element.videoWidth / this.element.videoHeight); this.updateAspectRatio(); this.element.addEventListener('resize', this.updateAspectRatio); } setProperties(props) { if (!(props.src instanceof HTMLVideoElement)) { updateVideoElement(this.element, props); } super.setProperties({ aspectRatio: this.aspectRatio, ...props, src: this.texture, }); } destroy() { super.destroy(); this.unsubscribeInvalidate(); this.texture.dispose(); this.element.remove(); this.element.removeEventListener('resize', this.updateAspectRatio); } }