element-web/src/components/views/elements/effects/EffectsOverlay.tsx

75 lines
2.6 KiB
TypeScript
Raw Normal View History

2020-10-21 15:29:25 +03:00
import React, { FunctionComponent, useEffect, useRef } from 'react';
import dis from '../../../../dispatcher/dispatcher';
import ICanvasEffect from './ICanvasEffect.js';
2020-10-21 15:48:11 +03:00
export type EffectsOverlayProps = {
roomWidth: number;
}
2020-10-21 15:29:25 +03:00
const EffectsOverlay: FunctionComponent<EffectsOverlayProps> = ({ roomWidth }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const effectsRef = useRef<Map<String, ICanvasEffect>>(new Map<String, ICanvasEffect>());
const lazyLoadEffectModule = async (name: string): Promise<ICanvasEffect> => {
2020-10-21 15:29:25 +03:00
if (!name) return null;
let effect = effectsRef.current[name] ?? null;
2020-10-21 15:29:25 +03:00
if (effect === null) {
try {
2020-10-21 15:43:09 +03:00
const { default: Effect } = await import(`./${name}`);
effect = new Effect();
effectsRef.current[name] = effect;
} catch (err) {
console.warn('Unable to load effect module at \'./${name}\'.', err)
}
}
return effect;
};
useEffect(() => {
2020-10-21 15:43:09 +03:00
const resize = () => {
canvasRef.current.height = window.innerHeight;
};
const onAction = (payload: { action: string }) => {
const actionPrefix = 'effects.';
if (payload.action.indexOf(actionPrefix) === 0) {
const effect = payload.action.substr(actionPrefix.length);
lazyLoadEffectModule(effect).then((module) => module?.start(canvasRef.current));
}
}
const dispatcherRef = dis.register(onAction);
const canvas = canvasRef.current;
canvas.height = window.innerHeight;
window.addEventListener('resize', resize, true);
2020-10-21 15:29:25 +03:00
return () => {
dis.unregister(dispatcherRef);
2020-10-21 16:15:26 +03:00
window.removeEventListener('resize', resize);
2020-10-21 15:56:04 +03:00
// eslint-disable-next-line react-hooks/exhaustive-deps
const currentEffects = effectsRef.current; // this is not a react node ref, warning can be safely ignored
2020-10-21 15:43:09 +03:00
for (const effect in currentEffects) {
const effectModule: ICanvasEffect = currentEffects[effect];
2020-10-21 15:56:04 +03:00
if (effectModule && effectModule.isRunning) {
2020-10-21 15:43:09 +03:00
effectModule.stop();
}
}
};
}, []);
return (
<canvas
ref={canvasRef}
2020-10-21 15:43:09 +03:00
width={roomWidth}
style={{
display: 'block',
zIndex: 999999,
pointerEvents: 'none',
position: 'fixed',
top: 0,
right: 0,
}}
/>
)
}
2020-10-21 15:43:09 +03:00
export default EffectsOverlay;