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.
React Native Skia provides powerful text rendering capabilities with support for custom fonts, text paths, glyphs, and paragraphs.
Text Component
Renders text at a specific position.
import { Canvas, Text, matchFont } from "@shopify/react-native-skia";
const font = matchFont({
fontFamily: "Helvetica",
fontSize: 24,
fontWeight: "bold",
});
<Canvas style={{ flex: 1 }}>
<Text x={50} y={100} text="Hello, Skia!" font={font} color="black" />
</Canvas>
Props
The text string to render
X-coordinate of the text baseline start
Y-coordinate of the text baseline
Font object created with matchFont() or Skia.Font()
Creating Fonts
Using matchFont
Match system fonts:
import { matchFont } from "@shopify/react-native-skia";
const regularFont = matchFont({
fontFamily: "Arial",
fontSize: 16,
});
const boldFont = matchFont({
fontFamily: "Arial",
fontSize: 16,
fontWeight: "bold",
});
const italicFont = matchFont({
fontFamily: "Arial",
fontSize: 16,
fontStyle: "italic",
});
Loading Custom Fonts
Use the useFonts hook:
import { useFonts, matchFont } from "@shopify/react-native-skia";
export default function CustomFontExample() {
const fontsLoaded = useFonts({
"Roboto-Regular": [require("./fonts/Roboto-Regular.ttf")],
"Roboto-Bold": [require("./fonts/Roboto-Bold.ttf")],
});
const font = matchFont({
fontFamily: "Roboto",
fontSize: 20,
});
if (!fontsLoaded) return null;
return (
<Canvas style={{ flex: 1 }}>
<Text x={50} y={100} text="Custom Font" font={font} />
</Canvas>
);
}
Imperative Font Creation
import { Skia, FontStyle } from "@shopify/react-native-skia";
const typeface = Skia.Typeface.MakeFreeTypeFaceFromData(
require("./fonts/MyFont.ttf")
);
const font = Skia.Font(typeface, 24);
TextPath
Renders text along a path.
import { Canvas, TextPath, Path, matchFont } from "@shopify/react-native-skia";
const font = matchFont({ fontSize: 20 });
const path = "M 50 150 Q 150 50 250 150";
<Canvas style={{ flex: 1 }}>
<Path path={path} style="stroke" strokeWidth={1} color="#ccc" />
<TextPath
text="Text along a curved path"
path={path}
font={font}
color="blue"
/>
</Canvas>
Props
Offset along the path where text starts
Glyphs
Render individual glyphs with precise positioning.
import { Canvas, Glyphs, matchFont } from "@shopify/react-native-skia";
const font = matchFont({ fontSize: 32 });
const glyphIDs = font.getGlyphIDs("Hello");
const glyphs = glyphIDs.map((id, i) => ({
id,
pos: { x: 50 + i * 25, y: 100 },
}));
<Canvas style={{ flex: 1 }}>
<Glyphs glyphs={glyphs} x={0} y={0} font={font} color="purple" />
</Canvas>
Props
Array of glyph objects with { id: number, pos: { x: number, y: number } }
Font containing the glyphs
TextBlob
Render pre-shaped text for better performance.
import { Canvas, TextBlob, Skia, matchFont } from "@shopify/react-native-skia";
const font = matchFont({ fontSize: 24 });
const textBlob = Skia.TextBlob.MakeFromText("Optimized Text", font);
<Canvas style={{ flex: 1 }}>
<TextBlob blob={textBlob} x={50} y={100} color="green" />
</Canvas>
Props
Paragraph
Render multi-line text with advanced layout.
import { Canvas, Paragraph, Skia, useFonts } from "@shopify/react-native-skia";
export default function ParagraphExample() {
const fontsLoaded = useFonts({
Roboto: [require("./Roboto-Regular.ttf")],
});
if (!fontsLoaded) return null;
const paragraphStyle = {
textAlign: TextAlign.Left,
};
const textStyle = {
color: Skia.Color("black"),
fontFamilies: ["Roboto"],
fontSize: 16,
};
const paragraph = Skia.ParagraphBuilder.Make(paragraphStyle)
.pushStyle(textStyle)
.addText("This is a paragraph with automatic line wrapping. ")
.addText("It can contain multiple lines and styles.")
.pop()
.build();
paragraph.layout(250); // Max width
return (
<Canvas style={{ flex: 1 }}>
<Paragraph paragraph={paragraph} x={50} y={50} width={250} />
</Canvas>
);
}
Font Metrics
Get measurements from fonts:
const font = matchFont({ fontSize: 24 });
// Get text width
const width = font.getTextWidth("Hello");
// Get bounding box
const bounds = font.measureText("Hello");
console.log(bounds); // { x, y, width, height }
// Get font metrics
const metrics = font.getMetrics();
console.log(metrics); // { ascent, descent, leading }
// Get glyph IDs
const glyphIDs = font.getGlyphIDs("Hello");
// Get glyph widths
const widths = font.getGlyphWidths(glyphIDs);
Text Effects
Gradient Text
import { Canvas, Text, LinearGradient, vec, matchFont } from "@shopify/react-native-skia";
const font = matchFont({ fontSize: 48, fontWeight: "bold" });
<Canvas style={{ flex: 1 }}>
<Text x={50} y={100} text="GRADIENT" font={font}>
<LinearGradient
start={vec(0, 0)}
end={vec(300, 0)}
colors={["#FF0080", "#7928CA", "#0070F3"]}
/>
</Text>
</Canvas>
Stroked Text
const font = matchFont({ fontSize: 48, fontWeight: "bold" });
<Canvas style={{ flex: 1 }}>
{/* Outline */}
<Text
x={50}
y={100}
text="OUTLINE"
font={font}
color="blue"
style="stroke"
strokeWidth={2}
/>
{/* Fill */}
<Text x={50} y={100} text="OUTLINE" font={font} color="white" />
</Canvas>
Shadow Text
import { Canvas, Text, Shadow, matchFont } from "@shopify/react-native-skia";
const font = matchFont({ fontSize: 36 });
<Canvas style={{ flex: 1 }}>
<Text x={50} y={100} text="Shadowed" font={font} color="black">
<Shadow dx={2} dy={2} blur={4} color="rgba(0,0,0,0.5)" />
</Text>
</Canvas>
- Use
TextBlob for static text that doesn’t change
- Load fonts once and reuse font objects
- Use
useMemo to cache font creation
- Avoid creating new font instances in render
- For dynamic text, consider using the simpler
Text component
Font Styling Options
const font = matchFont({
fontFamily: "System",
fontSize: 20,
fontStyle: "normal" | "italic",
fontWeight: "normal" | "bold" | 100-900,
});