Documentation Index
Fetch the complete documentation index at: https://mintlify.com/shopify/react-native-skia/llms.txt
Use this file to discover all available pages before exploring further.
Paths are the foundation for creating complex shapes in Skia. They can contain lines, curves, and multiple contours.
Creating Paths
Using Skia.Path
import { Skia } from "@shopify/react-native-skia";
const path = Skia.Path.Make();
path.moveTo(10, 10);
path.lineTo(100, 10);
path.lineTo(100, 100);
path.lineTo(10, 100);
path.close();
From SVG String
const path = Skia.Path.MakeFromSVGString(
"M 10 10 L 100 10 L 100 100 L 10 100 Z"
);
Path Methods
Movement Commands
moveTo
(x: number, y: number) => SkPath
Starts a new contour at the specified point
lineTo
(x: number, y: number) => SkPath
Draws a straight line to the specified point
rMoveTo
(dx: number, dy: number) => SkPath
Relative move (offset from current position)
rLineTo
(dx: number, dy: number) => SkPath
Relative line (offset from current position)
Curves
quadTo
(x1: number, y1: number, x2: number, y2: number) => SkPath
Draws a quadratic Bezier curvepath.moveTo(0, 100);
path.quadTo(50, 0, 100, 100); // control point, end point
cubicTo
(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number) => SkPath
Draws a cubic Bezier curvepath.moveTo(0, 100);
path.cubicTo(25, 0, 75, 0, 100, 100);
conicTo
(x1: number, y1: number, x2: number, y2: number, w: number) => SkPath
Draws a conic curve with weightpath.conicTo(50, 0, 100, 100, 0.5);
Arcs
arcToOval
(oval: SkRect, startAngle: number, sweepAngle: number, forceMoveTo: boolean) => SkPath
Draws an arc within an ovalconst oval = rect(0, 0, 100, 100);
path.arcToOval(oval, 0, 180, false);
arcToRotated
(rx: number, ry: number, xAxisRotate: number, useSmallArc: boolean, isCCW: boolean, x: number, y: number) => SkPath
Draws an SVG-style arcpath.moveTo(10, 50);
path.arcToRotated(40, 40, 0, false, true, 90, 50);
Shapes
addRect
(rect: SkRect, isCCW?: boolean) => SkPath
Adds a rectangle to the pathpath.addRect(rect(10, 10, 100, 100));
addRRect
(rrect: SkRRect, isCCW?: boolean) => SkPath
Adds a rounded rectanglepath.addRRect(rrect(rect(10, 10, 100, 100), 10, 10));
addCircle
(x: number, y: number, r: number) => SkPath
Adds a circlepath.addCircle(50, 50, 40);
addOval
(oval: SkRect, isCCW?: boolean, startIndex?: number) => SkPath
Adds an ellipsepath.addOval(rect(0, 0, 100, 50));
addPoly
(points: SkPoint[], close: boolean) => SkPath
Adds a polygon from pointspath.addPoly([
{ x: 50, y: 0 },
{ x: 100, y: 50 },
{ x: 50, y: 100 },
{ x: 0, y: 50 },
], true);
Path Operations
Closes the current contour with a line to the start point
Clears the path and releases memory
Clears the path but keeps allocated memorypath.rewind(); // Faster for reuse
Creates a copy of the pathconst pathCopy = path.copy();
transform
(matrix: InputMatrix) => SkPath
Transforms the path by a matrixconst matrix = Skia.Matrix();
matrix.translate(50, 50);
matrix.rotate(Math.PI / 4);
const transformed = path.transform(matrix);
offset
(dx: number, dy: number) => SkPath
Translates the pathconst moved = path.offset(20, 30);
Boolean Operations
op
(path: SkPath, op: PathOp) => boolean
Performs boolean operations on pathsimport { PathOp } from "@shopify/react-native-skia";
const result = path1.op(path2, PathOp.Union);
Operations:
PathOp.Difference: Subtract path2 from path1
PathOp.Intersect: Intersection of both paths
PathOp.Union: Combination of both paths
PathOp.XOR: Exclusive OR
PathOp.ReverseDifference: Subtract path1 from path2
Simplifies overlapping contours
Stroking
stroke
(opts?: StrokeOpts) => SkPath | null
Converts path to its stroked equivalentconst stroked = path.stroke({
width: 5,
join: StrokeJoin.Round,
cap: StrokeCap.Round,
});
dash
(on: number, off: number, phase: number) => boolean
Applies dash pattern to path
Measurement
Gets the bounding boxconst bounds = path.getBounds();
console.log(bounds); // { x, y, width, height }
Gets tight bounds (more accurate but slower)const tightBounds = path.computeTightBounds();
contains
(x: number, y: number) => boolean
Tests if a point is inside the pathconst isInside = path.contains(50, 50);
Checks if path has no verbsif (path.isEmpty()) {
console.log("Path is empty");
}
Path Interpolation
interpolate
(end: SkPath, weight: number, output?: SkPath) => SkPath | null
Interpolates between two pathsconst morphed = path1.interpolate(path2, 0.5);
isInterpolatable
(path: SkPath) => boolean
Checks if paths can be interpolatedif (path1.isInterpolatable(path2)) {
const morphed = path1.interpolate(path2, 0.5);
}
Path Trimming
trim
(start: number, end: number, isComplement: boolean) => SkPath | null
Trims path to a segment (0-1)const segment = path.trim(0.25, 0.75, false);
Fill Types
import { FillType } from "@shopify/react-native-skia";
path.setFillType(FillType.Winding); // Default
path.setFillType(FillType.EvenOdd);
path.setFillType(FillType.InverseWinding);
path.setFillType(FillType.InverseEvenOdd);
Path Component
import { Canvas, Path } from "@shopify/react-native-skia";
const path = Skia.Path.Make();
path.moveTo(50, 50);
path.lineTo(150, 50);
path.lineTo(100, 150);
path.close();
<Canvas style={{ flex: 1 }}>
<Path path={path} color="blue" />
</Canvas>
Examples
Rounded Path
const path = Skia.Path.Make();
path.moveTo(50, 100);
path.lineTo(150, 100);
path.arcToRotated(25, 25, 0, false, true, 150, 150);
path.lineTo(50, 150);
path.arcToRotated(25, 25, 0, false, true, 50, 100);
path.close();
Star Shape
const star = () => {
const path = Skia.Path.Make();
const points = 5;
const outerRadius = 50;
const innerRadius = 20;
for (let i = 0; i < points * 2; i++) {
const angle = (i * Math.PI) / points - Math.PI / 2;
const radius = i % 2 === 0 ? outerRadius : innerRadius;
const x = 100 + Math.cos(angle) * radius;
const y = 100 + Math.sin(angle) * radius;
if (i === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
path.close();
return path;
};
Animated Path
import { useSharedValue, withRepeat, withTiming } from "react-native-reanimated";
import { Canvas, Path, Skia } from "@shopify/react-native-skia";
const path1 = Skia.Path.MakeFromSVGString("M 50 50 L 150 50 L 100 150 Z");
const path2 = Skia.Path.MakeFromSVGString("M 50 150 L 150 150 L 100 50 Z");
export default function MorphingPath() {
const progress = useSharedValue(0);
useEffect(() => {
progress.value = withRepeat(
withTiming(1, { duration: 2000 }),
-1,
true
);
}, []);
return (
<Canvas style={{ flex: 1 }}>
<Path
path={() => path1.interpolate(path2, progress.value)}
color="purple"
/>
</Canvas>
);
}