Creating the Gooey Blob Effect in React Native using Skia

Ever seen those playful, blobby animations on websites where circles stick, stretch, and melt into each other like jelly? It’s like watching digital slime. That visual magic is called the gooey effect.
In the web world, this effect is often created with a mix of CSS filters, SVGs, and blurring tricks. But if you’re building with React Native, things get a little trickier. We don’t have CSS filters or native SVG filters out of the box.
So how do we make gooey magic happen in React Native?
How the Gooey Effect Works on the Web
The gooey effect on the web is mostly made using SVG filters, and the real star of the show is something called Gaussian blur.
Here’s the high-level idea:
Step 1: Gaussian Blur — Making Things Soft
When you blur a shape, it gets fuzzy around the edges. If two blurred shapes are close to each other, those fuzzy edges overlap and blend.
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" />
</filter>
This tells the browser: “Take the graphic (our blobs), and blur it with a softness of 10 pixels.”
Displayed two blue circles in an SVG, with a defined but unused blur filter.
The circles don’t physically touch, but the blur makes them look like they do.
Step 2: Color Matrix
So now we’ve got our circles blurred nice and soft around the edges. But right now, it’s just a visual overlap. The blobs look foggy, not gooey. To actually make them merge like sticky jelly we use something called a color matrix filter.
Here’s the updated SVG filter with the matrix added:
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 20 -10" result="goo" />
</filter>
What’s a Color Matrix Actually Doing?
It’s basically a 4x5 math grid that lets you change the look of pixels.
The first 3 rows keep the colors (red, green, blue) unchanged.
The last row is where the effect happens:
0 0 0 20 -10
boosts the alpha channel (transparency) Which makes the overlapping blurry parts look solid and connected.
It turns soft blurry overlaps into bold, sticky bridges between blobs — exactly the gooey merge we’re after!
Step 3: Putting the Blobs Back On Top
At this point, we’ve blurred the blobs (Step 1) and made them gooey using the color matrix (Step 2). But now they look like one weird melted shape we’ve lost the crisp edges of the original circles.
To bring back that clean look, we use a final SVG filter step: <feComposite>
This just blends the original shape back on top of the gooey version — like putting a shiny clean lid on a pot of slime.
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 20 -10" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop" />
</filter>
In the next section, we’ll talk about how to recreate this same feel in React Native even though we don’t have these exact filter tools available.
Recreating the Gooey Effect in React Native with Skia
Installation & Setup (Using Expo)
Start by installing the necessary dependencies.
Using Yarn
yarn add @shopify/react-native-skia
Or with npm
npm install @shopify/react-native-skia
Then make sure to rebuild your app:
npx expo prebuild
npx expo run:ios # or run:android
That’s it you now have a working Expo project with Skia support!
Note: If you’re using React Native CLI instead of Expo, you can follow the official Skia installation guide to set things up for your native project.
Setting Up the Skia Canvas
Now that we’ve installed everything, let’s get something on the screen. Before we dive into filters and effect, we’ll start by rendering some simple plain Circles using Skia.
Let’s update index.tsx with a simple canvas and a couple of overlapping circles:
import { Canvas, Circle } from "@shopify/react-native-skia";
import React from "react";
import { Dimensions, View } from "react-native";
const { width, height } = Dimensions.get("window");
const Index = () => {
return (
<View style={{ flex: 1 }}>
<Canvas style={{ flex: 1 }}>
<Circle cx={width / 2} cy={height / 2 - 20} r={50} color="#00BFFF" />
<Circle cx={width / 2} cy={height / 2 + 80} r={50} color="#00BFFF" />
</Canvas>
</View>
);
};
export default Index;
Canvas is your drawing area like a playground for blobs.
Circle draws a circle on that canvas. You can control its position with cx (center X), cy (center Y), and r (radius).
These two circles are overlapping slightly, setting the stage for gooeyness later.
Now that we got the basic circles on screen, it’s the time to implement the gooey effect using Skia’s Paint, Blur, and ColorMatrix.
Making It Gooey with Blur + ColorMatrix
What’s a Layer in Skia?
Skia lets us group multiple shapes together and apply visual effects to that group using the layer prop on a Group. This is super handy when you want to apply blur, filters, or blend modes across multiple objects.
In the following code we are wrapping our circles with <Group/>
and passing a layer property which we will implement next.
import { Canvas, Circle, Group, Paint } from "@shopify/react-native-skia";
import React, { useMemo } from "react";
import { Dimensions, View } from "react-native";
const { width, height } = Dimensions.get("window");
const Index = () => {
const layer = useMemo(() => {
return <Paint></Paint>;
}, []);
return (
<View style={{ flex: 1 }}>
<Canvas style={{ flex: 1 }}>
<Group layer={layer}>
<Circle cx={width / 2} cy={height / 2 - 20} r={50} color="#00BFFF" />
<Circle cx={width / 2} cy={height / 2 + 80} r={50} color="#00BFFF" />
</Group>
</Canvas>
</View>
);
};
export default Index;
Applying Blur Effect
We use Skia’s Blur
inside a Paint to make the edges of our circles soft and fuzzy this is the first step toward the gooey effect.
const layer = useMemo(() => {
return (
<Paint>
<Blur blur={10} />
</Paint>
);
}, []);
This makes each shape look a bit like it’s glowing. Showing that they melt together when they overlap.
Boost the Alpha with ColorMatrix
Blurring alone just softens the shapes, but to actually fuse them visually, we need to intensify the transparency (alpha) in the overlapping areas. We can do this by using ColorMatrix
from Skia.
ColorMatrix: The matrix has five columns, each with a red, green, blue, and alpha component. You can use the matrix for tasks like creating a color transformation.
Here’s the updated layer code with the ColorMatrix added:
const layer = useMemo(() => {
return (
<Paint>
<Blur blur={10} />
<ColorMatrix
matrix={[
//
1, 0, 0, 0, 0,
//
0, 1, 0, 0, 0,
//
0, 0, 1, 0, 0,
//
0, 0, 0, 20, 0,
]}
/>
</Paint>
);
}, []);
The first three rows leave your colors (R, G, B) untouched
The last row boosts the alpha channel
this makes overlapping blurred parts more visible and starts giving us that gooey vibe. but you might still see soft shadows and faded halos around each shape. Like below:
Let’s fix this strange effect on edges.
Add Bias to Cut Off Low Alpha
The last column in the color matrix is called the bias it offsets the RGBA values after scaling. By subtracting a bias in our case -5, we remove the low-opacity parts of the blur. This gives us clean, sharp effect.
const layer = useMemo(() => {
return (
<Paint>
<Blur blur={10} />
<ColorMatrix
matrix={[
//
1, 0, 0, 0, 0,
//
0, 1, 0, 0, 0,
//
0, 0, 1, 0, 0,
//
0, 0, 0, 20, -5,
]}
/>
</Paint>
);
}, []);
Let’s Run It and See it in Action
# ios
npx expo run:ios
# android
npx expo run:android
You should see two blobs that beautifully melt together at their overlap. That’s your first working gooey effect in React Native using Skia.
Full Code
import {
Blur,
Canvas,
Circle,
ColorMatrix,
Group,
Paint,
} from "@shopify/react-native-skia";
import React, { useMemo } from "react";
import { Dimensions, View } from "react-native";
const { width, height } = Dimensions.get("window");
const Index = () => {
const layer = useMemo(() => {
return (
<Paint>
<Blur blur={10} />
<ColorMatrix
matrix={[
//
1, 0, 0, 0, 0,
//
0, 1, 0, 0, 0,
//
0, 0, 1, 0, 0,
//
0, 0, 0, 20, -5,
]}
/>
</Paint>
);
}, []);
return (
<View style={{ flex: 1 }}>
<Canvas style={{ flex: 1 }}>
<Group layer={layer}>
<Circle cx={width / 2} cy={height / 2 - 20} r={50} color="#00BFFF" />
<Circle cx={width / 2} cy={height / 2 + 80} r={50} color="#00BFFF" />
</Group>
</Canvas>
</View>
);
};
export default Index;
Bonus: Make It Wiggle (with Reanimated)
Let’s add a tiny bit of life to our blobs using react-native-reanimated. We’ll animate the positions to give them a natural wiggle motion kind of like floating jelly.
Setup Animated Values
// Create animated shared values
const topCircleY = useSharedValue(height / 2 - 200);
const bottomCircleY = useSharedValue(height / 2 + 200);
const topCircleX = useSharedValue(width / 2);
const bottomCircleX = useSharedValue(width / 2);
Animate Positions
We can animate them using withRepeat + withTiming and pass those into Skia Circle components.
React.useEffect(() => {
// Vertical animation
topCircleY.value = withRepeat(
withTiming(height / 2, {
duration: 4000,
}),
-1,
true
);
// Vertical animation
bottomCircleY.value = withRepeat(
withTiming(height / 2, {
duration: 4000,
}),
-1,
true
);
// Horizontal animation
topCircleX.value = withRepeat(
withTiming(width / 2 + 30, {
duration: 2000,
}),
-1,
true
);
// Horizontal animation
bottomCircleX.value = withRepeat(
withTiming(width / 2 - 30, {
duration: 2000,
}),
-1,
true
);
}, []);
The above code
Moves both blobs back toward the center (vertically)
Adds gentle side-to-side motion (horizontally)
All animations loop back and forth forever (-1, true)
Use Animated Values in Skia Circle
Once topCircleX, topCircleY, etc. are animating, just pass them directly into Skia Circle components they accept SharedValue types out of the box.
<Canvas style={{ flex: 1 }}>
<Group layer={layer}>
<Circle cx={topCircleX} cy={topCircleY} r={50} color="#00BFFF" />
<Circle cx={bottomCircleX} cy={bottomCircleY} r={50} color="#00BFFF" />
</Group>
</Canvas>
Final Result
Wrapping Up
We took a fun visual effect often seen in web design and recreated it in React Native using Skia, ColorMatrix, and a little help from Reanimated.
Subscribe to my newsletter
Read articles from AKSHAY JADHAV directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

AKSHAY JADHAV
AKSHAY JADHAV
Software Engineer