@shopify/react-native-skia
Version:
High-performance React Native Graphics using Skia
156 lines (151 loc) • 5.02 kB
JavaScript
var _global;
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); }
import React, { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
import Rea from "../external/reanimated/ReanimatedProxy";
import { SkiaViewNativeId } from "../views/SkiaViewNativeId";
import SkiaPictureViewNativeComponent from "../specs/SkiaPictureViewNativeComponent";
import { SkiaSGRoot } from "../sksg/Reconciler";
import { Skia } from "../skia";
import { Platform } from "../Platform";
import { HAS_REANIMATED_3 } from "../external";
export const useCanvasRef = () => useRef(null);
const useReanimatedFrame = !HAS_REANIMATED_3 ? () => {} : Rea.useFrameCallback;
const measure = !HAS_REANIMATED_3 ? null : Rea.measure;
const useCanvasRefPriv = !HAS_REANIMATED_3 ? useRef : Rea.useAnimatedRef;
export const useCanvasSize = userRef => {
const ourRef = useCanvasRef();
const ref = userRef !== null && userRef !== void 0 ? userRef : ourRef;
const [size, setSize] = useState({
width: 0,
height: 0
});
useLayoutEffect(() => {
if (ref.current) {
ref.current.measure((_x, _y, width, height) => {
setSize({
width,
height
});
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return {
ref,
size
};
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isFabric = Boolean((_global = global) === null || _global === void 0 ? void 0 : _global.nativeFabricUIManager);
export const Canvas = ({
debug,
opaque,
children,
onSize,
colorSpace = "p3",
androidWarmup = false,
ref,
onLayout,
...viewProps
}) => {
if (onLayout && isFabric) {
console.error("<Canvas onLayout={onLayout} /> is not supported on the new architecture, to fix the issue, see: https://shopify.github.io/react-native-skia/docs/canvas/overview/#getting-the-canvas-size");
}
const viewRef = useCanvasRefPriv(null);
// Native ID
const nativeId = useMemo(() => {
return SkiaViewNativeId.current++;
}, []);
// Root
const root = useMemo(() => new SkiaSGRoot(Skia, nativeId), [nativeId]);
useReanimatedFrame(() => {
"worklet";
if (onSize && measure) {
var _viewRef$current;
const result =
// eslint-disable-next-line no-nested-ternary
Platform.OS === "web" ?
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
(_viewRef$current = viewRef.current) !== null && _viewRef$current !== void 0 && _viewRef$current.canvasRef ?
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
measure(viewRef.current.canvasRef) : {
width: 0,
height: 0
} :
// eslint-disable-next-line @typescript-eslint/no-explicit-any
measure(viewRef);
if (result) {
const {
width,
height
} = result;
if (onSize.value.width !== width || onSize.value.height !== height) {
onSize.value = {
width,
height
};
}
}
}
}, !!onSize);
// Render effects
useLayoutEffect(() => {
root.render(children);
}, [children, root, nativeId]);
useEffect(() => {
return () => {
root.unmount();
};
}, [root]);
// Component methods
useImperativeHandle(ref, () => ({
makeImageSnapshot: rect => {
return SkiaViewApi.makeImageSnapshot(nativeId, rect);
},
makeImageSnapshotAsync: rect => {
return SkiaViewApi.makeImageSnapshotAsync(nativeId, rect);
},
redraw: () => {
SkiaViewApi.requestRedraw(nativeId);
},
getNativeId: () => {
return nativeId;
},
measure: callback => {
var _viewRef$current2;
(_viewRef$current2 = viewRef.current) === null || _viewRef$current2 === void 0 || _viewRef$current2.measure(callback);
},
measureInWindow: callback => {
var _viewRef$current3;
(_viewRef$current3 = viewRef.current) === null || _viewRef$current3 === void 0 || _viewRef$current3.measureInWindow(callback);
}
}));
const onLayoutWeb = useCallback(e => {
if (onLayout) {
onLayout(e);
}
if (Platform.OS === "web" && onSize) {
const {
width,
height
} = e.nativeEvent.layout;
onSize.value = {
width,
height
};
}
}, [onLayout, onSize]);
return /*#__PURE__*/React.createElement(SkiaPictureViewNativeComponent, _extends({
ref: viewRef,
collapsable: false,
nativeID: `${nativeId}`,
debug: debug,
opaque: opaque,
colorSpace: colorSpace,
androidWarmup: androidWarmup,
onLayout: Platform.OS === "web" && (onSize || onLayout) ? onLayoutWeb : onLayout
}, viewProps));
};
//# sourceMappingURL=Canvas.js.map