React Native Skia vs React Native SVG vs react-native-canvas 2026
React Native Skia vs React Native SVG vs react-native-canvas 2026
TL;DR
Drawing 2D graphics in React Native — charts, custom UI, image filters, signatures, games, data visualization — requires choosing the right rendering layer. React Native Skia (from Shopify) runs Google's Skia graphics library on the UI thread via JSI (zero JS bridge), supports Reanimated animations, image filters, shaders, and text on paths — it's the most powerful option and ships in Expo SDK 46+. React Native SVG renders SVG primitives (<Rect>, <Circle>, <Path>, <Text>) using native SVG engines (AVFoundation on iOS, SVG on Android), integrates with React's component model naturally, and handles icon libraries and custom vector graphics well. react-native-canvas wraps a WebView with an HTML5 Canvas API — useful for porting web Canvas code to mobile but limited by WebView performance and the JS bridge overhead. For high-performance animations, image processing, and complex 2D rendering: React Native Skia. For vector graphics, icons, charts, and SVG-based custom UI: React Native SVG. For porting existing HTML5 Canvas code with minimal changes: react-native-canvas.
Key Takeaways
- Skia runs on UI thread — JSI + Worklets, zero bridge overhead, same thread as Reanimated
- Skia supports image filters — blur, color matrix, displacement maps, shader effects
- React Native SVG is the SVG standard — declarative primitives, no setup beyond install
- Skia supports shaders — GLSL-like
skslshaders for complex graphical effects - React Native SVG integrates with Victory Native — charting library on top of SVG
- react-native-canvas bridges WebView — compatible with web Canvas API but slowest
- Skia requires New Architecture or JSI — works with both Old and New arch via JSI bridge
Performance Comparison
React Native Skia JSI direct, UI thread, Reanimated-native
React Native SVG Native SVG engine, bridge serialization for updates
react-native-canvas WebView + postMessage, slowest, most compatible
React Native Skia: JSI-Powered 2D Graphics
React Native Skia wraps Google's Skia graphics engine (same as Flutter, Chrome, Android) with a React-based declarative API and JSI for zero-bridge rendering.
Installation
# For Expo:
npx expo install @shopify/react-native-skia
# For bare React Native:
npm install @shopify/react-native-skia
cd ios && pod install
Basic Shapes
import { Canvas, Circle, Rect, RoundedRect, Path, vec } from "@shopify/react-native-skia";
export function BasicShapes() {
return (
<Canvas style={{ width: 300, height: 300 }}>
{/* Circle */}
<Circle cx={80} cy={80} r={50} color="#6366f1" />
{/* Rectangle */}
<Rect x={150} y={30} width={100} height={100} color="#ec4899" />
{/* Rounded Rectangle */}
<RoundedRect
x={50}
y={180}
width={200}
height={80}
r={12}
color="#06b6d4"
/>
{/* Custom path */}
<Path
path="M 40 240 L 100 180 L 160 240 Z"
color="#10b981"
style="fill"
/>
</Canvas>
);
}
Gradients and Paint
import {
Canvas,
Rect,
Circle,
LinearGradient,
RadialGradient,
SweepGradient,
Paint,
vec,
} from "@shopify/react-native-skia";
export function GradientShapes() {
return (
<Canvas style={{ width: 300, height: 300 }}>
{/* Rect with linear gradient */}
<Rect x={20} y={20} width={120} height={120}>
<LinearGradient
start={vec(20, 20)}
end={vec(140, 140)}
colors={["#6366f1", "#ec4899"]}
/>
</Rect>
{/* Circle with radial gradient */}
<Circle cx={210} cy={80} r={60}>
<RadialGradient
c={vec(210, 80)}
r={60}
colors={["#fbbf24", "#f97316", "#ef4444"]}
/>
</Circle>
{/* Stroke with paint */}
<Circle cx={80} cy={220} r={50}>
<Paint
style="stroke"
strokeWidth={4}
color="#8b5cf6"
/>
</Circle>
</Canvas>
);
}
Animated with Reanimated
import { Canvas, Circle, Fill } from "@shopify/react-native-skia";
import { useEffect } from "react";
import {
useDerivedValue,
useSharedValue,
withRepeat,
withTiming,
} from "react-native-reanimated";
export function PulsatingCircle() {
const progress = useSharedValue(0);
useEffect(() => {
progress.value = withRepeat(withTiming(1, { duration: 1500 }), -1, true);
}, []);
// Derived values run on UI thread — no bridge
const radius = useDerivedValue(() => 40 + progress.value * 30);
const opacity = useDerivedValue(() => 1 - progress.value * 0.5);
return (
<Canvas style={{ width: 200, height: 200 }}>
<Circle
cx={100}
cy={100}
r={radius} // Animated — updates on UI thread
color="#6366f1"
opacity={opacity}
/>
</Canvas>
);
}
Image Filters (Blur, Color Matrix)
import {
Canvas,
Image,
Blur,
ColorMatrix,
useImage,
} from "@shopify/react-native-skia";
export function ImageFilters() {
const image = useImage(require("./photo.jpg"));
// Grayscale matrix
const grayscaleMatrix = [
0.21, 0.72, 0.07, 0, 0,
0.21, 0.72, 0.07, 0, 0,
0.21, 0.72, 0.07, 0, 0,
0, 0, 0, 1, 0,
];
if (!image) return null;
return (
<Canvas style={{ width: 300, height: 300 }}>
{/* Blurred image */}
<Image x={0} y={0} width={140} height={140} image={image} fit="cover">
<Blur blur={5} />
</Image>
{/* Grayscale image */}
<Image x={160} y={0} width={140} height={140} image={image} fit="cover">
<ColorMatrix matrix={grayscaleMatrix} />
</Image>
</Canvas>
);
}
Text and Custom Fonts
import {
Canvas,
Text,
useFont,
Skia,
Path,
TextPath,
} from "@shopify/react-native-skia";
export function SkiaText() {
const font = useFont(require("./Inter-Regular.ttf"), 24);
// Text on a circular path
const path = Skia.Path.Make();
path.addArc({ x: 50, y: 50, width: 200, height: 200 }, -90, 180);
if (!font) return null;
return (
<Canvas style={{ width: 300, height: 300 }}>
{/* Basic text */}
<Text
x={20}
y={50}
text="Hello Skia!"
font={font}
color="#e5e7eb"
/>
{/* Text on a path */}
<TextPath text="Text on a curve..." path={path} font={font} color="#6366f1" />
</Canvas>
);
}
React Native SVG: Declarative Vector Graphics
React Native SVG brings the SVG spec to React Native — same primitives as web SVG, familiar if you know SVG.
Installation
# Expo:
npx expo install react-native-svg
# Bare:
npm install react-native-svg
cd ios && pod install
Basic SVG Shapes
import Svg, {
Circle,
Rect,
Path,
Ellipse,
Line,
Polygon,
Text as SvgText,
Defs,
LinearGradient,
Stop,
ClipPath,
G,
} from "react-native-svg";
export function SvgShapes() {
return (
<Svg width={300} height={300}>
{/* Gradient definition */}
<Defs>
<LinearGradient id="grad1" x1="0" y1="0" x2="1" y2="1">
<Stop offset="0" stopColor="#6366f1" stopOpacity="1" />
<Stop offset="1" stopColor="#ec4899" stopOpacity="1" />
</LinearGradient>
</Defs>
{/* Circle with gradient */}
<Circle cx={80} cy={80} r={50} fill="url(#grad1)" />
{/* Rectangle */}
<Rect
x={150}
y={30}
width={100}
height={100}
rx={12}
fill="#ec4899"
/>
{/* Path (arrow) */}
<Path
d="M 50 200 L 100 150 L 150 200 L 130 200 L 130 250 L 70 250 L 70 200 Z"
fill="#10b981"
/>
{/* Text */}
<SvgText x={200} y={220} fontSize={16} fill="#e5e7eb" textAnchor="middle">
SVG Text
</SvgText>
</Svg>
);
}
Custom Icon Component
import Svg, { Path, G } from "react-native-svg";
interface IconProps {
size?: number;
color?: string;
}
// Custom SVG icon as a React component
export function CheckCircleIcon({ size = 24, color = "#10b981" }: IconProps) {
return (
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<Path
d="M22 11.08V12a10 10 0 11-5.93-9.14"
stroke={color}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
<Path
d="M22 4L12 14.01l-3-3"
stroke={color}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
);
}
Animated SVG with Reanimated
import Svg, { Circle, Path } from "react-native-svg";
import Animated, { useAnimatedProps, useSharedValue, withRepeat, withTiming } from "react-native-reanimated";
import { useEffect } from "react";
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
export function AnimatedProgressRing({
progress = 0.7,
size = 100,
color = "#6366f1",
}: {
progress?: number;
size?: number;
color?: string;
}) {
const radius = size / 2 - 8;
const circumference = 2 * Math.PI * radius;
const animatedProgress = useSharedValue(0);
useEffect(() => {
animatedProgress.value = withTiming(progress, { duration: 1000 });
}, [progress]);
const animatedProps = useAnimatedProps(() => ({
strokeDashoffset: circumference * (1 - animatedProgress.value),
}));
return (
<Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
{/* Background track */}
<Circle
cx={size / 2}
cy={size / 2}
r={radius}
stroke="#333"
strokeWidth={8}
fill="transparent"
/>
{/* Progress ring */}
<AnimatedCircle
cx={size / 2}
cy={size / 2}
r={radius}
stroke={color}
strokeWidth={8}
fill="transparent"
strokeDasharray={circumference}
strokeDashoffset={circumference} // Starting value
animatedProps={animatedProps}
strokeLinecap="round"
transform={`rotate(-90, ${size / 2}, ${size / 2})`}
/>
</Svg>
);
}
Victory Native (Charting on SVG)
import { VictoryBar, VictoryChart, VictoryTheme, VictoryAxis } from "victory-native";
const data = [
{ x: "Jan", y: 42 },
{ x: "Feb", y: 55 },
{ x: "Mar", y: 67 },
{ x: "Apr", y: 49 },
{ x: "May", y: 72 },
];
export function BarChart() {
return (
<VictoryChart theme={VictoryTheme.material} domainPadding={20}>
<VictoryAxis />
<VictoryAxis dependentAxis />
<VictoryBar data={data} style={{ data: { fill: "#6366f1" } }} />
</VictoryChart>
);
}
react-native-canvas: Web Canvas in React Native
react-native-canvas wraps a WebView with an HTML5 Canvas API — useful for porting web code.
Installation
npm install react-native-canvas react-native-webview
cd ios && pod install
Basic Canvas Drawing
import React, { useRef } from "react";
import Canvas, { CanvasRenderingContext2D } from "react-native-canvas";
import { View } from "react-native";
export function CanvasExample() {
function handleCanvas(canvas: Canvas | null) {
if (!canvas) return;
canvas.width = 300;
canvas.height = 300;
const ctx: CanvasRenderingContext2D = canvas.getContext("2d");
// Same API as web HTML5 Canvas
ctx.fillStyle = "#6366f1";
ctx.fillRect(50, 50, 100, 100);
ctx.beginPath();
ctx.arc(200, 100, 50, 0, Math.PI * 2);
ctx.fillStyle = "#ec4899";
ctx.fill();
// Gradient
const gradient = ctx.createLinearGradient(0, 200, 300, 300);
gradient.addColorStop(0, "#10b981");
gradient.addColorStop(1, "#06b6d4");
ctx.fillStyle = gradient;
ctx.fillRect(0, 200, 300, 100);
}
return (
<View>
<Canvas ref={handleCanvas} />
</View>
);
}
Feature Comparison
| Feature | React Native Skia | React Native SVG | react-native-canvas |
|---|---|---|---|
| Performance | ✅ Best (JSI) | Good (native SVG) | ⚠️ WebView-based |
| Reanimated | ✅ Native integration | ✅ Via Animated | No |
| Shader support | ✅ SkSL shaders | No | Limited |
| Image filters | ✅ Blur, ColorMatrix | Basic | Limited |
| SVG path API | ✅ Skia paths | ✅ SVG spec | Canvas paths |
| Web Canvas API | Different API | No | ✅ Compatible |
| Expo support | ✅ SDK 46+ | ✅ | No |
| New Architecture | ✅ JSI | ✅ | No |
| Text on path | ✅ | Via SVG | Canvas API |
| Font support | ✅ Custom fonts | ✅ System + SVG | Limited |
| Gradients | ✅ Linear/Radial/Sweep | ✅ Linear/Radial | ✅ |
| ClipPath | ✅ | ✅ | ✅ |
| Bundle overhead | ~4MB | ~500kB | Small (needs WebView) |
| npm weekly | 500k | 2.5M | 100k |
| GitHub stars | 6k | 7k | 1.5k |
When to Use Each
Choose React Native Skia if:
- High-performance animations (60fps+ on UI thread)
- Image processing — blur, color correction, filters
- Complex 2D rendering — games, drawing apps, signature pads
- Need shaders for advanced visual effects
- Using Reanimated extensively (Skia values are worklet-native)
- Building a data visualization with many animated elements
Choose React Native SVG if:
- Icon rendering and SVG icon libraries
- Simple charts via Victory Native or similar
- Custom UI components with vector shapes
- Familiar with SVG spec from web development
- Don't need animations beyond React's basic Animated API
- Lightweight package, broad compatibility needed
Choose react-native-canvas if:
- Porting existing web Canvas code to React Native
- Need the HTML5 Canvas API specifically (same methods)
- Simple drawing that doesn't require high performance
- Prototyping — not recommended for production high-performance use cases
- Learning project translating web to React Native
Methodology
Data sourced from React Native Skia documentation (shopify.github.io/react-native-skia), React Native SVG documentation (github.com/software-mansion/react-native-svg), react-native-canvas documentation (github.com/iddan/react-native-canvas), npm weekly download statistics as of February 2026, GitHub star counts as of February 2026, and performance benchmarks from Shopify's Engineering blog.
Related: React Native Reanimated vs Moti vs Skia animation libraries for animation approaches in React Native, or Victory Native vs react-native-chart-kit vs echarts RN charts for charting specifically.