Using SVG
Using SVG for vector UI and illustrations
On this pageGetting Started
There are situations where using vector graphics can be desirable over simple bitmaps. Vector graphics have the benefit of being resolution independent, at a performance cost.
rnue supports SVG through a GPU rendered ThorVG runtime.
Getting Started
To use SVG files with rnue you must install both react-native-svg and @rnue/react-native-svg.
npm i react-native-svg@15.15.5 @rnue/react-native-svgrnue requires a pinned version of react-native-svg. See the compatibility section for more information.
Once installed, link the native module provided by @rnue/react-native-svg:
npx @rnue/cli linkRead more about linking in the @rnue/cli section of the documentation.
After linking, you can use react-native-svg or any package that depends on it.
Displaying static SVG with <Image />
The simplest way to show an SVG is to do so using the <Image /> component.
import { Image } from "react-native";
export function Logo() {
return <Image source={require("./logo.svg")} />;
}This will load the file, rasterize it to a bitmap on mount, and with every subsequent resize and display it. Note that while this will allow you to display the SVG at any resolution, the SVG will still be rendered as a bitmap and suffer from zoom artifacts if inspected closer without resizing (for example, if projected as an actor component).
Performance Tradeoff
There is extra overhead due to the rasterization process upon loading the SVG and on every resize.
Rendering static SVG as an MSDF
For instances where it is desirable to inspect the SVG at variable scale without incurring a re-rasterization cost, it is possible to rasteriaze the SVG to a Multi-Channel Signed Distance Field. This is very similar to how Unreal Engine handles scale independent text rendering.
import { Image } from "react-native";
export function Icon() {
return (
<Image
source={require("./icon.svg")}
svgRasterizationMode="sdf"
/>
);
}There are certain conditions that must be met in order for an SVG to be rasterizable to an MSDF texture:
- ✅ SDF mode accepts paths, rectangles, circles, ellipses, polygons, and groups. All visible shapes must use one opaque color and one fill rule.
- ⛔ SDF mode rejects strokes, text, images, opacity, gradients, patterns, clips, masks, filters, and external references.
If the provided SDF is unable to be rasterized as an MSDF, it will throw an SvgRasterizationError error to be caught by the nearest error boundary. The error will contain a code property with one of the following error codes.
Values for the code property of SvgRasterizationError
- SVG_INVALID_ARGUMENT
- SVG_NOT_FOUND
- SVG_NOT_SVG
- SVG_DECODE_FAILED
- SVG_UNSUPPORTED_CONTENT
- SVG_RASTERIZATION_FAILED
- SVG_OUTPUT_TOO_LARGE
- SVG_BACKEND_UNAVAILABLE
- SVG_SDF_RENDERER_UNAVAILABLE
Dynamic SVG with react-native-svg
If you want to render SVG images dynamically with support for changing styles and hit testing for pointer events, use react-native-svg.
import Svg, { Circle, Path } from "react-native-svg";
export function StatusIcon() {
return (
<Svg width={32} height={32} viewBox="0 0 32 32">
<Circle cx={16} cy={16} r={14} fill="#2050b0" />
<Path d="M9 16l5 5 9-11" fill="none" stroke="white" strokeWidth={3} />
</Svg>
);
}The rnue backend composites each SVG root into one bitmap drawn into a buffer and preserves native nodes for updates, events, geometry and imperative methods.
Performance Tradeoff
Keep in mind that dynamically rendering SVG has a cost. Profile your use of SVG on your target hardware to ensure frame render times stay within your frame budget.
Nuances of dynamic SVG rendering
- SVG filter definitions have no effect. Elements that reference them render without the SVG filter. For brightness, opacity, or drop shadow, put the Svg in a React Native View. Then use the React Native filter style on that View.
- The retained ThorVG scene renders masks, clips, gradients, patterns, text, and references, on the GPU in Engine targets and through ThorVG's software canvas elsewhere. Pointer hit tests use visible fill, stroke, clip, text, and image geometry. The backend supports pointerEvents and concurrent touches. Imperative APIs query the same rendered revision that is visible on screen.
- Markers and textPath are not supported.
- The backend does not render foreignObject content.
- Declarative dynamic SVG content does not support SDF rendering.