Skip to main content
The Mask component allows you to mask content using either alpha or luminance values from a mask element. This is useful for creating complex shapes, text masks, and image effects.

Basic Usage

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

export default function MaskExample() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mask={
          <Circle cx={150} cy={150} r={100} color="white" />
        }
      >
        <Rect x={0} y={0} width={300} height={300} color="blue" />
      </Mask>
    </Canvas>
  );
}

Props

mask
ReactNode | ReactNode[]
required
The mask element(s). For alpha masks, white areas are opaque and black areas are transparent. For luminance masks, the brightness determines opacity.
children
ReactNode | ReactNode[]
required
The content to be masked
mode
'alpha' | 'luminance'
default:"'alpha'"
The masking mode:
  • alpha: Uses the alpha channel of the mask
  • luminance: Uses the luminance (brightness) of the mask
clip
boolean
default:"true"
If true, clips the content to the mask. If false, only applies the mask opacity without clipping.

Alpha Masking

Alpha masking uses the alpha channel of the mask to determine opacity:
import { Canvas, Mask, LinearGradient, Rect, Circle, vec } from "@shopify/react-native-skia";

export default function AlphaMask() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mode="alpha"
        mask={
          <Circle cx={150} cy={150} r={100}>
            <LinearGradient
              start={vec(0, 0)}
              end={vec(300, 0)}
              colors={["black", "white"]}
            />
          </Circle>
        }
      >
        <Rect x={0} y={0} width={300} height={300} color="purple" />
      </Mask>
    </Canvas>
  );
}

Luminance Masking

Luminance masking uses the brightness of the mask:
import { Canvas, Mask, Image, Text, matchFont } from "@shopify/react-native-skia";

const font = matchFont({
  fontFamily: "Arial",
  fontSize: 72,
  fontWeight: "bold",
});

export default function LuminanceMask() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mode="luminance"
        mask={
          <Text x={50} y={150} text="MASK" font={font} color="white" />
        }
      >
        <Image
          image={require("./background.png")}
          x={0}
          y={0}
          width={300}
          height={300}
          fit="cover"
        />
      </Mask>
    </Canvas>
  );
}

Text Masking

Create text-shaped masks:
import { Canvas, Mask, Text, Rect, LinearGradient, matchFont, vec } from "@shopify/react-native-skia";

const font = matchFont({
  fontFamily: "Helvetica",
  fontSize: 96,
  fontWeight: "bold",
});

export default function TextMask() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mask={
          <Text x={50} y={200} text="HELLO" font={font} />
        }
      >
        <Rect x={0} y={0} width={400} height={400}>
          <LinearGradient
            start={vec(0, 0)}
            end={vec(400, 400)}
            colors={["#FF0080", "#7928CA", "#0070F3"]}
          />
        </Rect>
      </Mask>
    </Canvas>
  );
}

Complex Masks

Combine multiple shapes in a mask:
import { Canvas, Mask, Group, Circle, Rect } from "@shopify/react-native-skia";

export default function ComplexMask() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mask={
          <Group>
            <Circle cx={100} cy={150} r={60} color="white" />
            <Circle cx={200} cy={150} r={60} color="white" />
            <Circle cx={150} cy={200} r={60} color="white" />
          </Group>
        }
      >
        <Rect x={0} y={0} width={300} height={300} color="cyan" />
      </Mask>
    </Canvas>
  );
}

Image Masking

Use an image as a mask:
import { Canvas, Mask, Image, Rect, useImage } from "@shopify/react-native-skia";

export default function ImageMask() {
  const maskImage = useImage(require("./mask.png"));
  
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        mask={
          maskImage && (
            <Image
              image={maskImage}
              x={0}
              y={0}
              width={300}
              height={300}
              fit="cover"
            />
          )
        }
      >
        <Rect x={0} y={0} width={300} height={300} color="orange" />
      </Mask>
    </Canvas>
  );
}

Non-Clipping Masks

Apply mask opacity without clipping:
import { Canvas, Mask, Circle, Rect, RadialGradient, vec } from "@shopify/react-native-skia";

export default function NonClippingMask() {
  return (
    <Canvas style={{ flex: 1 }}>
      <Mask
        clip={false}
        mask={
          <Circle cx={150} cy={150} r={100}>
            <RadialGradient
              c={vec(150, 150)}
              r={100}
              colors={["white", "black"]}
            />
          </Circle>
        }
      >
        <Rect x={0} y={0} width={300} height={300} color="green" />
      </Mask>
    </Canvas>
  );
}

How It Works

The Mask component internally uses blend modes and layers to achieve the masking effect:
  1. Creates an offscreen layer
  2. Draws the mask with appropriate color filter (for luminance mode)
  3. Draws the content with dstIn blend mode to apply the mask
  4. Composites the result back to the canvas

Performance Tips

  • Masks create offscreen buffers, so use them judiciously
  • Simple shapes are more performant than complex paths or images
  • Alpha mode is slightly faster than luminance mode
  • Reuse mask elements when possible

Build docs developers (and LLMs) love