GLCanvas.js 3.74 KB
Newer Older
1
const invariant = require("invariant");
2 3 4
const React = require("react-native");
const {
  Component,
5
  requireNativeComponent
6 7
} = React;

8
const captureFrame = require("./GLCanvas.captureFrame");
9

10 11 12
const serializeOption = config =>
config.format + ":" + config.type + ":" + config.quality;

13 14 15 16 17
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas, {
  nativeOnly: {
    onGLChange: true,
    onGLProgress: true,
    onGLCaptureFrame: true
18
  }
19 20 21 22 23 24 25 26 27 28 29 30 31
});

function defer() {
  const deferred = {};
  const promise = new Promise(function(resolve, reject) {
    deferred.resolve = resolve;
    deferred.reject  = reject;
  });
  deferred.promise = promise;
  return deferred;
}

class GLCanvas extends Component {
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

  componentWillMount () {
    this._pendingCaptureFrame = {};
  }

  componentWillUnmount () {
    Object.keys(this._pendingCaptureFrame).forEach(key =>
      this._pendingCaptureFrame[key].reject(new Error("GLCanvas is unmounting")));
    this._pendingCaptureFrame = null;
  }

  addPendingCaptureFrame (config) {
    const key = serializeOption(config);
    return this._pendingCaptureFrame[key] || (
      (captureFrame(React.findNodeHandle(this.refs.native), config),
      this._pendingCaptureFrame[key] = defer())
    );
  }

  captureFrame (configArg) {
    let config;
    if (configArg) {
      invariant(typeof configArg==="object", "captureFrame takes an object option in parameter");
      let nb = 0;
      if ("format" in configArg) {
        invariant(
          typeof configArg.format === "string",
          "captureFrame({format}): format must be a string (e.g: 'base64'), Got: '%s'",
          configArg.format);
        if (configArg.format === "file") invariant(
          typeof configArg.filePath === "string" && configArg.filePath,
          "captureFrame({filePath}): filePath must be defined when using 'file' format and be an non-empty string, Got: '%s'",
          configArg.filePath);
        nb ++;
      }
      if ("type" in configArg) {
        invariant(
          typeof configArg.type === "string",
          "captureFrame({type}): type must be a string (e.g: 'png', 'jpg'), Got: '%s'",
          configArg.type);
        nb ++;
      }
      if ("quality" in configArg) {
        invariant(
          typeof configArg.quality === "number" &&
          configArg.quality >= 0 &&
          configArg.quality <= 1,
          "captureFrame({quality}): quality must be a number between 0 and 1, Got: '%s'",
          configArg.quality);
        nb ++;
      }
      if ("filePath" in configArg) {
        nb ++;
      }
      const keys = Object.keys(configArg);
      invariant(keys.length === nb, "captureFrame(config): config must be an object with {format, type, quality, filePath}, found some invalid keys in '%s'", keys);
      config = configArg;
89
    }
90 91 92 93 94 95 96
    return this.addPendingCaptureFrame({
      format: "base64",
      type: "png",
      quality: 1,
      filePath: "",
      ...config
    }).promise;
97
  }
98 99 100 101 102 103 104 105 106 107 108

  onGLCaptureFrame = ({ nativeEvent: { error, result, config } }) => {
    const key = serializeOption(config);
    invariant(key in this._pendingCaptureFrame, "capture '%s' is not scheduled in this._pendingCaptureFrame", key);
    if (error) {
      this._pendingCaptureFrame[key].reject(error);
    }
    else {
      this._pendingCaptureFrame[key].resolve(result);
    }
    delete this._pendingCaptureFrame[key];
109
  }
110

111
  render () {
112
    const { width, height, onLoad, onProgress, eventsThrough, ...restProps } = this.props;
113 114 115
    return <GLCanvasNative
      ref="native"
      {...restProps}
116 117 118 119
      onGLLoad={onLoad ? onLoad : null}
      onGLProgress={onProgress ? onProgress : null}
      onGLCaptureFrame={this.onGLCaptureFrame}
      pointerEvents={eventsThrough ? "none" : "auto"}
120 121 122 123 124 125
      style={{ width, height }}
    />;
  }
}

module.exports = GLCanvas;