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.
The Paragraph API provides advanced text layout capabilities including multi-line text, text wrapping, alignment, and rich text formatting.
Paragraph
The Paragraph component renders complex text layouts with automatic line breaking and advanced typography.
| Name | Type | Description |
|---|
| paragraph | SkParagraph | Paragraph object |
| x | number | X coordinate |
| y | number | Y coordinate |
| width | number | Maximum width for layout |
import { Canvas, Paragraph, Skia, useFonts } from "@shopify/react-native-skia";
import { useMemo } from "react";
const ParagraphDemo = () => {
const fontMgr = useFonts({
Roboto: [require("./Roboto-Regular.ttf")]
});
const paragraph = useMemo(() => {
if (!fontMgr) return null;
const paraStyle = Skia.ParagraphStyle();
const textStyle = Skia.TextStyle();
textStyle.setColor(Skia.Color("black"));
textStyle.setFontFamilies(["Roboto"]);
textStyle.setFontSize(16);
const builder = Skia.ParagraphBuilder.Make(paraStyle, fontMgr);
builder.pushStyle(textStyle);
builder.addText(
"This is a paragraph with automatic line wrapping and advanced text layout."
);
const para = builder.build();
para.layout(300); // Layout with max width of 300
return para;
}, [fontMgr]);
if (!paragraph) return null;
return (
<Canvas style={{ width: 320, height: 200 }}>
<Paragraph paragraph={paragraph} x={10} y={10} width={300} />
</Canvas>
);
};
Creating Paragraphs
ParagraphBuilder
Use ParagraphBuilder to construct complex text layouts:
import { Skia } from "@shopify/react-native-skia";
// Create paragraph style
const paraStyle = Skia.ParagraphStyle();
// Create paragraph builder
const builder = Skia.ParagraphBuilder.Make(paraStyle, fontMgr);
// Add styled text
const textStyle = Skia.TextStyle();
textStyle.setColor(Skia.Color("blue"));
textStyle.setFontSize(18);
builder.pushStyle(textStyle);
builder.addText("Styled text");
builder.pop();
// Build and layout
const paragraph = builder.build();
paragraph.layout(width);
Paragraph Methods
The SkParagraph interface provides methods for layout and measurement:
Layout
// Must be called before rendering
paragraph.layout(300); // Max width in pixels
Measurements
// Get dimensions (after layout)
const height = paragraph.getHeight();
const maxWidth = paragraph.getMaxWidth();
const longestLine = paragraph.getLongestLine();
// Get intrinsic widths
const minWidth = paragraph.getMinIntrinsicWidth();
const maxIntrinsicWidth = paragraph.getMaxIntrinsicWidth();
Hit Testing
// Get glyph position at coordinates
const position = paragraph.getGlyphPositionAtCoordinate(x, y);
console.log("Character index:", position);
Line Metrics
Get detailed information about each line:
const lines = paragraph.getLineMetrics();
lines.forEach((line) => {
console.log({
startIndex: line.startIndex,
endIndex: line.endIndex,
isHardBreak: line.isHardBreak,
ascent: line.ascent,
descent: line.descent,
height: line.height,
width: line.width,
left: line.left,
baseline: line.baseline,
lineNumber: line.lineNumber
});
});
Text Selection
Get bounding boxes for text ranges:
// Get rects for character range
const rects = paragraph.getRectsForRange(0, 10);
rects.forEach((rect) => {
console.log(rect.x, rect.y, rect.width, rect.height);
});
Placeholders
Get positions of inline placeholders (for images, etc.):
const placeholders = paragraph.getRectsForPlaceholders();
placeholders.forEach(({ rect, direction }) => {
console.log("Placeholder:", rect);
console.log("Direction:", direction);
});
Text Styles
Basic Styling
const textStyle = Skia.TextStyle();
// Color and size
textStyle.setColor(Skia.Color("#3366FF"));
textStyle.setFontSize(18);
// Font family
textStyle.setFontFamilies(["Roboto", "Arial"]);
// Background color
textStyle.setBackgroundColor(Skia.Color("yellow"));
// Foreground paint (for gradients, etc.)
const paint = Skia.Paint();
paint.setShader(gradient);
textStyle.setForegroundPaint(paint);
Font Styling
import { FontWeight, FontSlant } from "@shopify/react-native-skia";
textStyle.setFontStyle({
weight: FontWeight.Bold,
slant: FontSlant.Italic
});
Decorations
// Underline, overline, line-through
textStyle.setDecoration(TextDecoration.Underline);
textStyle.setDecorationColor(Skia.Color("red"));
textStyle.setDecorationThickness(2);
Shadows
textStyle.addShadow({
color: Skia.Color("rgba(0, 0, 0, 0.3)"),
offset: { x: 2, y: 2 },
blurRadius: 4
});
Paragraph Styles
Text Alignment
const paraStyle = Skia.ParagraphStyle();
// Alignment options: Left, Right, Center, Justify
paraStyle.setTextAlign(TextAlign.Center);
Text Direction
// For RTL languages
paraStyle.setTextDirection(TextDirection.RTL);
Line Height
// Set line height multiplier
paraStyle.setHeightMultiplier(1.5);
Max Lines
// Limit number of lines
paraStyle.setMaxLines(3);
// Set ellipsis for overflow
paraStyle.setEllipsis("...");
Rich Text Example
Create multi-styled text in a single paragraph:
const createRichText = (fontMgr: SkTypefaceFontProvider) => {
const paraStyle = Skia.ParagraphStyle();
paraStyle.setTextAlign(TextAlign.Left);
const builder = Skia.ParagraphBuilder.Make(paraStyle, fontMgr);
// Heading
const heading = Skia.TextStyle();
heading.setColor(Skia.Color("black"));
heading.setFontSize(24);
heading.setFontFamilies(["Roboto"]);
builder.pushStyle(heading);
builder.addText("Rich Text Example\n\n");
builder.pop();
// Body text
const body = Skia.TextStyle();
body.setColor(Skia.Color("#333"));
body.setFontSize(16);
body.setFontFamilies(["Roboto"]);
builder.pushStyle(body);
builder.addText("This paragraph contains ");
// Bold text
const bold = Skia.TextStyle();
bold.setColor(Skia.Color("#333"));
bold.setFontSize(16);
bold.setFontStyle({ weight: FontWeight.Bold });
builder.pushStyle(bold);
builder.addText("bold");
builder.pop();
builder.addText(" and ");
// Colored text
const colored = Skia.TextStyle();
colored.setColor(Skia.Color("blue"));
colored.setFontSize(16);
builder.pushStyle(colored);
builder.addText("colored");
builder.pop();
builder.addText(" text.");
const paragraph = builder.build();
paragraph.layout(300);
return paragraph;
};