High-performance React Native Graphics using Skia
—
Core rendering infrastructure providing canvas components and low-level view access for graphics rendering in React Native Skia.
The main canvas component for rendering Skia graphics with React Native integration.
/**
* Main canvas component for rendering Skia graphics
* @param props - Canvas configuration and children
* @returns JSX canvas element
*/
function Canvas(props: CanvasProps): JSX.Element;
interface CanvasProps extends Omit<ViewProps, "onLayout"> {
/** Enable debug mode to show performance metrics */
debug?: boolean;
/** Make canvas opaque for better performance when no transparency needed */
opaque?: boolean;
/** Shared value to receive canvas size updates */
onSize?: SharedValue<SkSize>;
/** Color space for rendering (p3 for wide gamut, srgb for standard) */
colorSpace?: "p3" | "srgb";
/** Ref for accessing canvas methods */
ref?: React.Ref<CanvasRef>;
/** Child components to render */
children?: React.ReactNode;
}Usage Examples:
import React from "react";
import { Canvas, Circle, Paint } from "@shopify/react-native-skia";
// Basic canvas
export function BasicCanvas() {
return (
<Canvas style={{ width: 300, height: 300 }}>
<Circle cx={150} cy={150} r={50}>
<Paint color="red" />
</Circle>
</Canvas>
);
}
// Canvas with debug and size tracking
export function ConfiguredCanvas() {
const size = useSharedValue({ width: 0, height: 0 });
return (
<Canvas
style={{ flex: 1 }}
debug={true}
opaque={true}
colorSpace="p3"
onSize={size}
>
{/* graphics content */}
</Canvas>
);
}Reference object providing imperative access to canvas operations.
interface CanvasRef {
/** Create a snapshot image of the canvas content */
makeImageSnapshot(rect?: SkRect): SkImage;
/** Asynchronously create a snapshot image of the canvas content */
makeImageSnapshotAsync(rect?: SkRect): Promise<SkImage>;
/** Force the canvas to redraw */
redraw(): void;
/** Get the native view identifier */
getNativeId(): number;
/** Measure the canvas dimensions */
measure(callback: MeasureOnSuccessCallback): void;
/** Measure the canvas position in window coordinates */
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void;
}
// Measurement callback types
type MeasureOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number
) => void;
type MeasureInWindowOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number
) => void;Usage Examples:
import React, { useRef } from "react";
import { Canvas, CanvasRef } from "@shopify/react-native-skia";
function CanvasWithSnapshot() {
const canvasRef = useRef<CanvasRef>(null);
const takeSnapshot = () => {
if (canvasRef.current) {
const image = canvasRef.current.makeImageSnapshot();
// Use the image...
}
};
const takeAsyncSnapshot = async () => {
if (canvasRef.current) {
const image = await canvasRef.current.makeImageSnapshotAsync();
// Use the image...
}
};
return (
<Canvas ref={canvasRef} style={{ width: 300, height: 300 }}>
{/* content */}
</Canvas>
);
}Utility hooks for working with canvas components.
/**
* Hook to create a typed canvas reference
* @returns Ref object for Canvas component
*/
function useCanvasRef(): RefObject<CanvasRef>;
/**
* Hook to get canvas size with automatic updates
* @param userRef - Optional existing canvas ref to use
* @returns Object with ref and size state value
*/
function useCanvasSize(userRef?: RefObject<CanvasRef>): {
ref: RefObject<CanvasRef>;
size: SkSize;
};Usage Examples:
import { useCanvasRef, useCanvasSize } from "@shopify/react-native-skia";
function ComponentWithCanvasHooks() {
// Simple ref hook
const canvasRef = useCanvasRef();
// Size tracking hook
const { ref: sizeRef, size } = useCanvasSize();
return (
<Canvas ref={canvasRef} style={{ width: 300, height: 300 }}>
{/* Use size.value.width and size.value.height */}
</Canvas>
);
}Functions for rendering React elements to images and pictures outside of the main canvas.
/**
* Render a React element to a Skia picture
* @param element - React element containing Skia components
* @param bounds - Optional bounds for the picture
* @returns Promise resolving to SkPicture
*/
function drawAsPicture(
element: ReactElement,
bounds?: SkRect
): Promise<SkPicture>;
/**
* Render a React element to a Skia image
* @param element - React element containing Skia components
* @param size - Size of the output image
* @returns Promise resolving to SkImage
*/
function drawAsImage(
element: ReactElement,
size: SkSize
): Promise<SkImage>;
/**
* Convert a Skia picture to an image
* @param picture - Source SkPicture to convert
* @param size - Size of the output image
* @returns SkImage
*/
function drawAsImageFromPicture(
picture: SkPicture,
size: SkSize
): SkImage;
/**
* Check if currently running on the main JavaScript thread
* @returns Boolean indicating main thread status
*/
function isOnMainThread(): boolean;Usage Examples:
import { drawAsImage, drawAsPicture, Skia } from "@shopify/react-native-skia";
async function createOffscreenImage() {
// Create image from React element
const image = await drawAsImage(
<Circle cx={50} cy={50} r={25}>
<Paint color="blue" />
</Circle>,
{ width: 100, height: 100 }
);
return image;
}
async function createPicture() {
// Create reusable picture
const picture = await drawAsPicture(
<Rect x={0} y={0} width={100} height={100}>
<Paint color="green" />
</Rect>
);
// Convert to image when needed
const image = drawAsImageFromPicture(picture, { width: 100, height: 100 });
return { picture, image };
}Lower-level view component for rendering SkPicture objects directly.
/**
* Lower-level view component for rendering SkPicture objects
*/
class SkiaPictureView extends React.Component<SkiaPictureViewProps> {
/** Create an image snapshot of the view content */
makeImageSnapshot(rect?: SkRect): SkImage;
/** Request the view to redraw */
redraw(): void;
/** Get the native view identifier */
readonly nativeId: number;
}
interface SkiaPictureViewProps extends SkiaPictureViewNativeProps {
/** Rendering mode for the picture view */
mode?: "default" | "continuous";
}
interface SkiaPictureViewNativeProps {
/** Enable debug mode */
debug?: boolean;
/** Optional size change callback */
onSize?: (size: SkSize) => void;
/** Make view opaque for performance */
opaque?: boolean;
}Low-level API interface for direct view manipulation.
interface ISkiaViewApi {
/** Set a JSI property on a native view */
setJsiProperty<T>(nativeId: number, name: string, value: T): void;
/** Request a view to redraw */
requestRedraw(nativeId: number): void;
/** Create an image snapshot of a view */
makeImageSnapshot(nativeId: number, rect?: SkRect): SkImage;
/** Asynchronously create an image snapshot of a view */
makeImageSnapshotAsync(nativeId: number, rect?: SkRect): Promise<SkImage>;
/** Get the size of a view */
size(nativeId: number): SkSize;
}// Base view properties
interface NativeSkiaViewProps {
debug?: boolean;
opaque?: boolean;
}
interface SkiaBaseViewProps extends NativeSkiaViewProps {
onSize?: SharedValue<SkSize>;
}
// Size and measurement types
interface SkSize {
width: number;
height: number;
}
interface SkRect {
x: number;
y: number;
width: number;
height: number;
}Install with Tessl CLI
npx tessl i tessl/npm-shopify--react-native-skia