gre / gl-react

gl-react – React library to write and compose WebGL shaders

Home Page:https://gl-react-cookbook.surge.sh

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to translate timeLoop.js to react version

wlex-club opened this issue · comments

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;
}

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

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}}/>
}