theatre/packages/plugin-r3f/src/components/ReferenceWindow.tsx
2021-06-18 13:05:06 +02:00

69 lines
1.7 KiB
TypeScript

import type {VFC} from 'react'
import React, {useEffect, useLayoutEffect, useRef} from 'react'
import {useEditorStore} from '../store'
import shallow from 'zustand/shallow'
import type {WebGLRenderer} from 'three'
import useMeasure from 'react-use-measure'
interface ReferenceWindowProps {
height: number
}
const ReferenceWindow: VFC<ReferenceWindowProps> = ({height}) => {
const canvasRef = useRef<HTMLCanvasElement>(null)
const [gl] = useEditorStore((state) => [state.gl], shallow)
const [ref, bounds] = useMeasure()
useLayoutEffect(() => {
if (gl) {
ref(gl?.domElement)
}
}, [gl, ref])
useEffect(() => {
let animationHandle: number
const draw = (gl: WebGLRenderer) => () => {
animationHandle = requestAnimationFrame(draw(gl))
if (!gl.domElement) {
return
}
const width = (gl.domElement.width / gl.domElement.height) * height
const ctx = canvasRef.current!.getContext('2d')!
// https://stackoverflow.com/questions/17861447/html5-canvas-drawimage-how-to-apply-antialiasing
ctx.imageSmoothingQuality = 'high'
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, width, height)
ctx.drawImage(gl.domElement, 0, 0, width, height)
}
if (gl) {
draw(gl)()
}
return () => {
cancelAnimationFrame(animationHandle)
}
}, [gl, height])
return gl?.domElement ? (
<div className="rounded overflow-hidden shadow-2xl">
<canvas
ref={canvasRef}
width={
((bounds.width || gl.domElement.width) /
(bounds.height || gl.domElement.height)) *
height
}
height={height}
/>
</div>
) : null
}
export default ReferenceWindow