-
Notifications
You must be signed in to change notification settings - Fork 624
/
useVideoTexture.tsx
40 lines (38 loc) 路 1.21 KB
/
useVideoTexture.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import * as THREE from 'three'
import { useEffect } from 'react'
import { useThree } from '@react-three/fiber'
import { suspend, preload, clear } from 'suspend-react'
interface VideoTextureProps extends HTMLVideoElement {
unsuspend?: 'canplay' | 'canplaythrough' | 'loadstart' | 'loadedmetadata'
start?: boolean
}
export function useVideoTexture(src: string, props: Partial<VideoTextureProps>) {
const { unsuspend, start, crossOrigin, muted, loop, ...rest } = {
unsuspend: 'loadedmetadata',
crossOrigin: 'Anonymous',
muted: true,
loop: true,
start: true,
playsInline: true,
...props,
}
const gl = useThree((state) => state.gl)
const texture = suspend<[url: string], () => Promise<THREE.VideoTexture>>(
() =>
new Promise((res, rej) => {
const video = Object.assign(document.createElement('video'), {
src,
crossOrigin,
loop,
muted,
...rest,
})
const texture = new THREE.VideoTexture(video)
texture.encoding = gl.outputEncoding
video.addEventListener(unsuspend, () => res(texture))
}),
[src]
)
useEffect(() => void (start && texture.image.play()), [texture, start])
return texture
}