Skip to main content
The Canvas component is the root of your Skia drawing. You can treat it as a regular React Native view and assign a view style. Behind the scenes, it uses its own React renderer.

Properties

NameTypeDescription
style?ViewStyleView style
ref?Ref<SkiaView>Reference to the SkiaView object
onSize?SharedValue<Size>Reanimated value to which the canvas size will be assigned
androidWarmup?booleanDraw the first frame directly on the Android compositor. Use for static icons or fully opaque drawings—animated or translucent canvases can misrender

Canvas Size

The size of the canvas is available on both the UI and JS thread.

UI Thread

The onSize property receives a shared value that updates whenever the canvas size changes:
import { useSharedValue, useDerivedValue } from "react-native-reanimated";
import { Fill, Canvas, Rect } from "@shopify/react-native-skia";

const Demo = () => {
  const size = useSharedValue({ width: 0, height: 0 });
  const rect = useDerivedValue(() => {
    const { width, height } = size.value;
    return { x: 0, y: 0, width, height };
  });
  
  return (
    <Canvas style={{ flex: 1 }} onSize={size}>
      <Rect color="cyan" rect={rect} />
    </Canvas>
  );
};

JS Thread

To get the canvas size on the JS thread, use useLayoutEffect and measure(). We provide a useCanvasSize hook for convenience:
import { Canvas, Rect, useCanvasSize } from "@shopify/react-native-skia";

const Demo = () => {
  const { ref, size: { width, height } } = useCanvasSize();
  
  return (
    <Canvas style={{ flex: 1 }} ref={ref}>
      <Rect color="cyan" rect={{ x: 0, y: 0, width, height }} />
    </Canvas>
  );
};
This is equivalent to:
import { useLayoutEffect, useState } from "react";
import { Canvas, Rect, useCanvasRef } from "@shopify/react-native-skia";

const Demo = () => {
  const ref = useCanvasRef();
  const [rect, setRect] = useState({ x: 0, y: 0, width: 0, height: 0 });
  
  useLayoutEffect(() => {
    ref.current?.measure((_x, _y, width, height) => {
      setRect({ x: 0, y: 0, width, height });
    });
  }, []);
  
  return (
    <Canvas style={{ flex: 1 }} ref={ref}>
      <Rect color="cyan" rect={rect} />
    </Canvas>
  );
};

Getting a Canvas Snapshot

You can save your drawings as an image using the makeImageSnapshotAsync method. This returns a promise that resolves to an Image object. It executes on the UI thread, ensuring access to the same Skia context as your on-screen canvases, including textures. If your drawing doesn’t contain textures, you can use the synchronous makeImageSnapshot method.

Example

import { useEffect } from "react";
import { Canvas, useCanvasRef, Circle } from "@shopify/react-native-skia";

export const Demo = () => {
  const ref = useCanvasRef();
  
  useEffect(() => {
    setTimeout(() => {
      // You can pass an optional rectangle
      // to only save part of the image
      const image = ref.current?.makeImageSnapshot();
      if (image) {
        // Use image in an <Image> component
        // Or save to file using encodeToBytes -> Uint8Array
        const bytes = image.encodeToBytes();
        console.log({ bytes });
      }
    }, 1000);
  });
  
  return (
    <Canvas style={{ flex: 1 }} ref={ref}>
      <Circle r={128} cx={128} cy={128} color="red" />
    </Canvas>
  );
};

Accessibility

The Canvas component supports the same properties as a View component, including accessibility properties. You can make elements inside the canvas accessible by overlaying views on top of your canvas. This is the same recipe used for applying gestures on specific canvas elements.

Build docs developers (and LLMs) love