You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.0 KiB
TypeScript
116 lines
3.0 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
|
|
import styles from './gradients.module.css';
|
|
import { initGrainFilter } from './grainPostProcessing';
|
|
import { InitThreeOptions, initThree } from './initThree';
|
|
import { initScene } from './initScene';
|
|
import { initGradient } from './initGradients';
|
|
import Stats from 'stats.js';
|
|
|
|
const threeCanvas = (
|
|
canvas: HTMLCanvasElement,
|
|
viewportSize: InitThreeOptions,
|
|
initTimeOffset: number = 0
|
|
) => {
|
|
const { renderer, clock } = initThree(canvas, viewportSize);
|
|
const { scene, camera, updateSize: updateCameraSize } = initScene(renderer);
|
|
const {
|
|
render: renderGradient,
|
|
updateSize: updateGradientSize,
|
|
unload: unloadGradinet,
|
|
} = initGradient(scene, renderer);
|
|
const { render: renderFrame, resize: resizeFrame } = initGrainFilter(
|
|
renderer,
|
|
scene,
|
|
camera
|
|
);
|
|
//const stats = new Stats();
|
|
// the number will decide which information will be displayed
|
|
// 0 => FPS Frames rendered in the last second. The higher the number the better.
|
|
// 1 => MS Milliseconds needed to render a frame. The lower the number the better.
|
|
// 2 => MB MBytes of allocated memory. (Run Chrome with --enable-precise-memory-info)
|
|
// 3 => CUSTOM User-defined panel support.
|
|
//stats.showPanel(0);
|
|
|
|
//document.body.appendChild(stats.dom);
|
|
|
|
let elapsedTime = 0;
|
|
let delta = 0;
|
|
let isActive = true;
|
|
|
|
const animate = () => {
|
|
if (!isActive) return;
|
|
//stats.begin();
|
|
elapsedTime = clock.elapsedTime + initTimeOffset;
|
|
delta = clock.getDelta();
|
|
|
|
renderGradient(elapsedTime, delta);
|
|
renderFrame(elapsedTime, delta);
|
|
|
|
//stats.end();
|
|
requestAnimationFrame(animate);
|
|
};
|
|
|
|
const resizeCanvas = (width: number, height: number) => {
|
|
renderer.setSize(width, height);
|
|
updateCameraSize();
|
|
updateGradientSize();
|
|
resizeFrame();
|
|
};
|
|
|
|
animate();
|
|
resizeCanvas(viewportSize.width, viewportSize.height);
|
|
|
|
const unload = () => {
|
|
isActive = false;
|
|
unloadGradinet();
|
|
renderer.dispose();
|
|
};
|
|
|
|
return {
|
|
resizeCanvas,
|
|
unload,
|
|
};
|
|
};
|
|
|
|
export function Gradients() {
|
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
const [timeOffset] = useState(Math.random() * 1000);
|
|
|
|
useEffect(() => {
|
|
try {
|
|
const canvas = threeCanvas(
|
|
canvasRef.current as HTMLCanvasElement,
|
|
{
|
|
width: rootRef.current?.clientWidth || 0,
|
|
height: rootRef.current?.clientHeight || 0,
|
|
},
|
|
timeOffset
|
|
);
|
|
|
|
const resize = () => {
|
|
canvas.resizeCanvas(
|
|
rootRef.current?.clientWidth || 0,
|
|
rootRef.current?.clientHeight || 0
|
|
);
|
|
};
|
|
|
|
window.addEventListener('resize', resize);
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', resize);
|
|
|
|
canvas.unload();
|
|
};
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}, [timeOffset]);
|
|
|
|
return (
|
|
<div className={styles.root} ref={rootRef}>
|
|
<canvas className={styles.canvas} ref={canvasRef}></canvas>
|
|
</div>
|
|
);
|
|
} |