How to translate timeLoop.js to react version
wlex-club opened this issue · comments
WLEX commented
I am not good at the flow language so i want to translate timeLoop.js to react,but i failed
//@flow
import React, { PureComponent } from "react";
import raf from "raf";
import hoistNonReactStatics from "hoist-non-react-statics";
// NB this is only an utility for the examples
export default (
C: ReactClass<*>,
{ refreshRate = 60 }: { refreshRate?: number } = {}
): ReactClass<*> => {
class TL extends PureComponent {
static displayName = `timeLoop(${C.displayName||C.name||""})`;
state: { time: number };
state = {
time: 0,
tick: 0,
};
_r: any;
componentDidMount() {
this.onPausedChange(this.props.paused);
}
componentWillReceiveProps({ paused }) {
if (this.props.paused !== paused) {
this.onPausedChange(paused);
}
}
componentWillUnmount() {
raf.cancel(this._r);
}
startLoop = () => {
let startTime: number, lastTime: number;
let interval = 1000 / refreshRate;
lastTime = -interval;
const loop = (t: number) => {
this._r = raf(loop);
if (!startTime) startTime = t;
if (t - lastTime > interval) {
lastTime = t;
this.setState({
time: t - startTime,
tick: this.state.tick + 1,
});
}
};
this._r = raf(loop);
};
onPausedChange = paused => {
if (paused) {
raf.cancel(this._r);
}
else {
this.startLoop();
}
};
render() {
return <C
{...this.props}
{...this.state}
/>;
}
};
hoistNonReactStatics(TL, C);
return TL;
}
@greweb commented
Sorry that this code is a bit cryptic.
@vle326 : Here is a simpler version written in more modern React code
https://github.com/gre/shaderday.com/blob/master/components/Visual.js#L5-L15
Jacopo Marrone commented
Begin exploring gl-react
yersterday and found difficult to use that class.
This is what i used in React Hooks way.
import { useCallback, useEffect, useRef, useState } from "react";
type FrameLoop = {
/** Elapsed time since the first frame execution. Number in seconds, */
time: number;
/** Index number of the frame */
tick: number;
}
type Options = {
/** FPS that the loop should have */
refreshRate?: number;
}
export const useRenderFrameLoop = (options?:Options) => {
const {refreshRate = 60} = options || {};
const [state, setState] = useState<FrameLoop>({
time: 0,
tick: 0,
});
useEffect(() => {
let rafRef: ReturnType<typeof window.requestAnimationFrame>;
let startTime: number;
let lastTime: number;
let interval = 1000 / refreshRate;
lastTime = -interval;
const loop: FrameRequestCallback = (t) => {
rafRef = window.requestAnimationFrame(loop);
if (!startTime) startTime = t;
if (t - lastTime > interval) {
lastTime = t;
const elapsedTime = t - startTime;
setState((state) => ({
time: elapsedTime,
tick: state.tick + 1,
}));
}
};
rafRef = window.requestAnimationFrame(loop);
// cleanup
return () => {
if (rafRef) window.cancelAnimationFrame(rafRef);
};
}, [refreshRate]);
return state;
};
// Demo Consumer
const AnimateLoopExample = () => {
const {time} = useRenderFrameLoop({refreshRate:60});
return <Node uniforms={{time}}/>
}