Filters
Five filter components attach to a shape's paint as declarative children: <Blur> and <DropShadow> (image filters), <ColorMatrix> and <ColorBlend> (color filters), and <MaskBlur> (a mask filter). They render nothing themselves — the parent shape merges them into its paint.
Blur and DropShadow
<Blur> blurs the whole drawing layer by a Gaussian sigma. A number blurs uniformly; {x, y} blurs per axis:
<Circle cx={110} cy={100} radius={60} color="#3b82f6">
<Blur blur={8} />
</Circle>
<Rect x={190} y={40} width={120} height={120} color="#22c55e">
<Blur blur={{ x: 2, y: 14 }} />
</Rect><DropShadow> renders a blurred copy of the drawing behind it, offset by dx/dy, in color. Unlike <Blur>, the shape itself stays crisp on top:
<Circle cx={100} cy={95} radius={55} color="#f59e0b">
<DropShadow dx={0} dy={10} blur={10} color="#00000055" />
</Circle>
<RRect x={180} y={35} width={140} height={110} radii={16} color="#8b5cf6">
<DropShadow dx={12} dy={4} blur={6} color="#ef444466" />
</RRect>Composition in declaration order
Several filters of the same kind compose in declaration order — the first declared is applied first. A soft blur under a drop shadow:
<Path path={FLOWER} color="#ec4899">
<Blur blur={2} />
<DropShadow dx={0} dy={14} blur={8} color="#00000044" />
</Path>ColorMatrix and ColorBlend
<ColorMatrix> runs a 20-number, row-major 4×5 matrix over the drawing's colors (Skia layout: R/G/B/A rows plus a translation column). The classic luminance weights turn anything grayscale; the W3C matrix makes sepia:
const GRAYSCALE = [
0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0, 0, 0,
1, 0,
];
<Path path={FLOWER} color="#ec4899">
<ColorMatrix matrix={GRAYSCALE} />
</Path>;An invalid matrix (wrong length or non-finite values) is dropped — the shape draws unfiltered.
<ColorBlend> combines a constant color with the drawing via any of the 28 blend modes. mode="src-in" replaces all color while keeping the drawn alpha — a cheap recolor:
<Path path={FLOWER} color="#ec4899">
<ColorBlend mode="src-in" color="#0ea5e9" />
</Path>MaskBlur
<MaskBlur> feathers the drawing's alpha mask. style selects how the inside is treated — "normal" (default, fuzzy inside and outside), "inner" (feathered edge drawn inside the shape), plus "solid" and "outer":
<Circle cx={110} cy={100} radius={70} color="#14b8a6">
<MaskBlur blur={30} />
</Circle>
<Circle cx={260} cy={100} radius={70} color="#f43f5e">
<MaskBlur blur={30} style="inner" />
</Circle>Filters inside <Paint>
A filter placed inside a <Paint style="stroke"> child applies to the stroke paint only — the shape's fill draws unfiltered:
<Path path={new Path2D().addCircle(170, 100, 60)} color="#94a3b8">
<Paint style="stroke" color="#6366f1" strokeWidth={10}>
<Blur blur={4} />
</Paint>
</Path>Inherited filters also arrive through Group paint inheritance, like the other paint attributes.
Group-level effects — the layer prop
Filters placed directly on a Group ride paint inheritance: every descendant applies them to its own drawing, so overlapping shapes stay separate. When you want the effects to run on the subtree as a whole — the classic gooey/liquid look — use the layer prop (RN-Skia semantics):
// Gooey: blur → alpha threshold → soften, applied to the COMPOSITED subtree.
// Overlaps fuse into a metaball; per-shape inheritance cannot do that.
const GOOEY = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 18, -7];
<Group
layer={
<Paint>
<Blur blur={12} />
<ColorMatrix matrix={GOOEY} />
<Blur blur={2} />
</Paint>
}
>
<Circle cx={40} cy={60} radius={26} color="#ec4899" />
<Circle cx={84} cy={68} radius={26} color="#ec4899" />
</Group>;layer={true}composites the subtree offscreen with no effects — useful with the Group's ownopacity(the exact group-opacity lane) or to isolate a subtree. The<Paint>'s other props (color,style, stroke attributes, shaders) are ignored; the layer's alpha is the Group'sopacity.- Clearing: set
layer={false}. Simply removing the prop does nothing — prop removal fires the setters withnull, which is a no-op by design. - Cost: each layer-bearing group costs one offscreen buffer per frame (clipped to its visible area). Prefer it for effect composition, not as a default grouping wrapper.
- Text and images rasterize into the layer like everything else — a group blur softens glyphs together with the shapes around them.
Further reading
- FiltersDemo.tsx — every filter and the stroke-only variant, live
- GooeyDemo.tsx — the layer prop: gooey fusion vs per-shape inheritance,
layer={true}, text through a group blur - Painting — the
<Paint>override and inheritance - Text — a
ColorMatrixover a whole paragraph