SVG Images
Draw an SVG (see SVG Support).
If the root dimensions are in absolute units, the width/height properties have no effect since the initial viewport is fixed.
Name | Type | Description |
---|---|---|
svg | SVG | SVG Image. |
width? | number | Width of the destination image. This is used to resolve the initial viewport when the root SVG width is specified in relative units. |
height? | number | Height of the destination image. This is used to resolve the initial viewport when the root SVG height is specified in relative units. |
x? | number | Optional displayed x coordinate of the svg container. |
y? | number | Optional displayed y coordinate of the svg container. |
The ImageSVG
component doesn't follow the same painting rules as other components.
see applying effects.
Example
tsx
import {Canvas ,ImageSVG ,useSVG } from "@shopify/react-native-skia";constImageSVGDemo = () => {// Alternatively, you can pass an SVG URL directly// for instance: const svg = useSVG("https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg");constsvg =useSVG (require ("../../assets/tiger.svg"));return (<Canvas style ={{flex : 1 }}>{svg && (<ImageSVG svg ={svg }width ={256}height ={256}/>)}</Canvas >);};
tsx
import {Canvas ,ImageSVG ,useSVG } from "@shopify/react-native-skia";constImageSVGDemo = () => {// Alternatively, you can pass an SVG URL directly// for instance: const svg = useSVG("https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg");constsvg =useSVG (require ("../../assets/tiger.svg"));return (<Canvas style ={{flex : 1 }}>{svg && (<ImageSVG svg ={svg }width ={256}height ={256}/>)}</Canvas >);};
You can also use an inlined string as SVG (using Skia.SVG.MakeFromString
):
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia } from "@shopify/react-native-skia";constsvg =Skia .SVG .MakeFromString (`<svg viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='31' cy='325' r='120px' fill='#c02aaa'/></svg>`)!;export constSVG = () => {return (<Canvas style ={{flex : 1 }}><ImageSVG svg ={svg }x ={0}y ={0}width ={290}height ={500}/></Canvas >);};
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia } from "@shopify/react-native-skia";constsvg =Skia .SVG .MakeFromString (`<svg viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='31' cy='325' r='120px' fill='#c02aaa'/></svg>`)!;export constSVG = () => {return (<Canvas style ={{flex : 1 }}><ImageSVG svg ={svg }x ={0}y ={0}width ={290}height ={500}/></Canvas >);};
Scaling the SVG
As mentionned above, if the root dimensions are in absolute units, the width/height properties have no effect since the initial viewport is fixed. However you can access these values and use the fitbox function.
Example
In the example below we scale the SVG to the canvas width and height.
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,Group } from "@shopify/react-native-skia";constsvg =Skia .SVG .MakeFromString (`<svg viewBox='0 0 20 20' width="20" height="20" xmlns='http://www.w3.org/2000/svg'><circle cx='10' cy='10' r='10' fill='#00ffff'/></svg>`)!;constwidth = 256;constheight = 256;constsrc =rect (0, 0,svg .width (),svg .height ());constdst =rect (0, 0,width ,height );export constSVG = () => {return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}><ImageSVG svg ={svg }x ={0}y ={0}width ={20}height ={20} /></Group ></Canvas >);};
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,Group } from "@shopify/react-native-skia";constsvg =Skia .SVG .MakeFromString (`<svg viewBox='0 0 20 20' width="20" height="20" xmlns='http://www.w3.org/2000/svg'><circle cx='10' cy='10' r='10' fill='#00ffff'/></svg>`)!;constwidth = 256;constheight = 256;constsrc =rect (0, 0,svg .width (),svg .height ());constdst =rect (0, 0,width ,height );export constSVG = () => {return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}><ImageSVG svg ={svg }x ={0}y ={0}width ={20}height ={20} /></Group ></Canvas >);};
Applying Effects
The ImageSVG
component doesn't follow the same painting rules as other components.
This is because behind the scene, we use the SVG module from Skia.
However you can apply effets using the layer
property.
Opacity Example
In the example below we apply an opacity effect via the ColorMatrix
component.
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,useSVG ,Group ,Paint ,OpacityMatrix ,ColorMatrix } from "@shopify/react-native-skia";constwidth = 256;constheight = 256;export constSVG = () => {consttiger =useSVG (require ("./tiger.svg"));if (!tiger ) {return null;}constsrc =rect (0, 0,tiger .width (),tiger .height ());constdst =rect (0, 0,width ,height );return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}layer ={<Paint ><ColorMatrix matrix ={OpacityMatrix (0.5)} /></Paint >}><ImageSVG svg ={tiger }x ={0}y ={0}width ={800}height ={800} /></Group ></Canvas >);};
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,useSVG ,Group ,Paint ,OpacityMatrix ,ColorMatrix } from "@shopify/react-native-skia";constwidth = 256;constheight = 256;export constSVG = () => {consttiger =useSVG (require ("./tiger.svg"));if (!tiger ) {return null;}constsrc =rect (0, 0,tiger .width (),tiger .height ());constdst =rect (0, 0,width ,height );return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}layer ={<Paint ><ColorMatrix matrix ={OpacityMatrix (0.5)} /></Paint >}><ImageSVG svg ={tiger }x ={0}y ={0}width ={800}height ={800} /></Group ></Canvas >);};
Blur Example
In the example below we apply a blur image filter to the SVG.
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,useSVG ,Group ,Paint ,Blur } from "@shopify/react-native-skia";constwidth = 256;constheight = 256;export constSVG = () => {consttiger =useSVG (require ("./tiger.svg"));if (!tiger ) {return null;}constsrc =rect (0, 0,tiger .width (),tiger .height ());constdst =rect (0, 0,width ,height );return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}layer ={<Paint ><Blur blur ={10} /></Paint >}><ImageSVG svg ={tiger }x ={0}y ={0}width ={800}height ={800} /></Group ></Canvas >);};
tsx
importReact from "react";import {Canvas ,ImageSVG ,Skia ,rect ,fitbox ,useSVG ,Group ,Paint ,Blur } from "@shopify/react-native-skia";constwidth = 256;constheight = 256;export constSVG = () => {consttiger =useSVG (require ("./tiger.svg"));if (!tiger ) {return null;}constsrc =rect (0, 0,tiger .width (),tiger .height ());constdst =rect (0, 0,width ,height );return (<Canvas style ={{flex : 1 }}><Group transform ={fitbox ("contain",src ,dst )}layer ={<Paint ><Blur blur ={10} /></Paint >}><ImageSVG svg ={tiger }x ={0}y ={0}width ={800}height ={800} /></Group ></Canvas >);};
Result
SVG Support
The SVG module from Skia displays SVGs as images. We expect most SVG files to render correctly out of the box, especially if they come from Figma or Illustrator. However, please be aware of some of the quirks below when using it. Text elements current won't render and any external XML elements such as XLink or CSS won't render. If your SVG doesn't render correctly and you've considered all the items below, please file an issue.
Text
Currently text rendering is not supported
CSS Styles
CSS styles included in SVG are not supported.
A tool like SVGO can help with converting CSS style attributes to SVG attributes if possible.
You can use it online here.
For instance, it can normalize CSS style attributes that contain transformations to the proper transform
property.
RGBA Colors
The RGBA color syntax is not supported. Instead, it would help if you used the fill-opacity
and stroke-opacity
attributes. Consider the example below.
xml
<circler="10"cx="10"cy="10"fill="rgba(100, 200, 300, 0.5)"stroke="rgba(100, 200, 300, 0.8)"/>
xml
<circler="10"cx="10"cy="10"fill="rgba(100, 200, 300, 0.5)"stroke="rgba(100, 200, 300, 0.8)"/>
Would need to be rewritten as:
xml
<circler="10"cx="10"cy="10"fill="rgb(100, 200, 300)"fill-opacity="0.5"stroke="rgb(100, 200, 300)"stroke-opacity="0.8"/>
xml
<circler="10"cx="10"cy="10"fill="rgb(100, 200, 300)"fill-opacity="0.5"stroke="rgb(100, 200, 300)"stroke-opacity="0.8"/>
The opacity
attribute also applies to both the fill
and stroke
attributes.
Non Supported Elements
Below is the list of non-supported element. Often these SVGs can be rewritten to not use these elements.
<altGlyph>
(deprecated)<animate>
<cursor>
(deprecated)<feComponentTransfer>
<feConvolveMatrix>
<feTile>
<feDropShadow>
<font>
(deprecated)<foreignObject>
<glyph>
(deprecated)<script>
<view>
Font Family
When rendering your SVG with Skia, all fonts available in your app are also available to your SVG.
However, the way you can set the font-family
attribute is as flexible as on the web.
jsx
// ✅ This is really all that is supported:<text font-family="MyFont" />// ❌ This won't work. If MyFont is available, this syntax will be accepted.// but it will never fallback to monospace<text font-family="MyFont, monospace" />// ❌ The single quote syntax won't work either.<text font-family="'MyFont'" />
jsx
// ✅ This is really all that is supported:<text font-family="MyFont" />// ❌ This won't work. If MyFont is available, this syntax will be accepted.// but it will never fallback to monospace<text font-family="MyFont, monospace" />// ❌ The single quote syntax won't work either.<text font-family="'MyFont'" />
Inlined SVGs
Some SVGs contain inlined SVGs via the <image>
or <feImage>
elements. This is not supported.
Gradient Templates
The deprecated xlink:href
attribute is not supported in gradients.
You can use the href
attribute instead.
However, we found that it doesn't appear to be adequately supported.
We would recommend avoiding using it.
Fallbacks
Some SVG with issues display nicely in the browser because they are very tolerant of errors. We found that the Skia SVG module is much less forgiving.