@shopify/react-native-skia
Version:
High-performance React Native Graphics using Skia
143 lines (139 loc) • 5.62 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SkiaBaseWebView = void 0;
var _react = _interopRequireDefault(require("react"));
var _JsiSkSurface = require("../skia/web/JsiSkSurface");
var _Platform = require("../Platform");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* global HTMLCanvasElement */
const pd = _Platform.Platform.PixelRatio;
class SkiaBaseWebView extends _react.default.Component {
constructor(props) {
super(props);
_defineProperty(this, "_surface", null);
_defineProperty(this, "_unsubscriptions", []);
_defineProperty(this, "_canvas", null);
_defineProperty(this, "_canvasRef", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "_redrawRequests", 0);
_defineProperty(this, "requestId", 0);
_defineProperty(this, "width", 0);
_defineProperty(this, "height", 0);
_defineProperty(this, "onLayout", this.onLayoutEvent.bind(this));
}
unsubscribeAll() {
this._unsubscriptions.forEach(u => u());
this._unsubscriptions = [];
}
onLayoutEvent(evt) {
const {
CanvasKit
} = global;
// Reset canvas / surface on layout change
const canvas = this._canvasRef.current;
if (canvas) {
this.width = canvas.clientWidth;
this.height = canvas.clientHeight;
canvas.width = this.width * pd;
canvas.height = this.height * pd;
const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);
const ctx = canvas.getContext("webgl2");
if (ctx) {
ctx.drawingBufferColorSpace = "display-p3";
}
if (!surface) {
throw new Error("Could not create surface");
}
this._surface = new _JsiSkSurface.JsiSkSurface(CanvasKit, surface);
this._canvas = this._surface.getCanvas();
this.redraw();
}
// Call onLayout callback if it exists
if (this.props.onLayout) {
this.props.onLayout(evt);
}
}
getSize() {
return {
width: this.width,
height: this.height
};
}
componentDidMount() {
// Start render loop
this.tick();
}
componentDidUpdate() {
this.redraw();
}
componentWillUnmount() {
this.unsubscribeAll();
cancelAnimationFrame(this.requestId);
// eslint-disable-next-line max-len
// https://stackoverflow.com/questions/23598471/how-do-i-clean-up-and-unload-a-webgl-canvas-context-from-gpu-after-use
// https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context
// We delete the context, only if the context has been intialized
if (this._surface) {
var _this$_canvasRef$curr;
(_this$_canvasRef$curr = this._canvasRef.current) === null || _this$_canvasRef$curr === void 0 || (_this$_canvasRef$curr = _this$_canvasRef$curr.getContext("webgl2")) === null || _this$_canvasRef$curr === void 0 || (_this$_canvasRef$curr = _this$_canvasRef$curr.getExtension("WEBGL_lose_context")) === null || _this$_canvasRef$curr === void 0 || _this$_canvasRef$curr.loseContext();
}
}
/**
* Creates a snapshot from the canvas in the surface
* @param rect Rect to use as bounds. Optional.
* @returns An Image object.
*/
makeImageSnapshot(rect) {
var _this$_surface, _this$_surface2;
this._canvas.clear(CanvasKit.TRANSPARENT);
this.renderInCanvas(this._canvas);
(_this$_surface = this._surface) === null || _this$_surface === void 0 || _this$_surface.ref.flush();
return (_this$_surface2 = this._surface) === null || _this$_surface2 === void 0 ? void 0 : _this$_surface2.makeImageSnapshot(rect);
}
/**
* Override to render
*/
/**
* Sends a redraw request to the native SkiaView.
*/
tick() {
if (this._redrawRequests > 0) {
this._redrawRequests = 0;
if (this._canvas) {
var _this$_surface3;
const canvas = this._canvas;
canvas.clear(Float32Array.of(0, 0, 0, 0));
canvas.save();
canvas.scale(pd, pd);
this.renderInCanvas(canvas);
canvas.restore();
(_this$_surface3 = this._surface) === null || _this$_surface3 === void 0 || _this$_surface3.ref.flush();
}
}
this.requestId = requestAnimationFrame(this.tick.bind(this));
}
redraw() {
this._redrawRequests++;
}
render() {
const {
debug = false,
...viewProps
} = this.props;
return /*#__PURE__*/_react.default.createElement(_Platform.Platform.View, _extends({}, viewProps, {
onLayout: this.onLayout
}), /*#__PURE__*/_react.default.createElement("canvas", {
ref: this._canvasRef,
style: {
display: "flex",
flex: 1
}
}));
}
}
exports.SkiaBaseWebView = SkiaBaseWebView;
//# sourceMappingURL=SkiaBaseWebView.js.map