Group
The Group component is an essential construct in React Native Skia. Group components can be deeply nested with one another. It can apply the following operations to its children:
Name | Type | Description |
---|---|---|
transform? | Transform2d | Same API that's in React Native. The default origin of the transformation is, however, different. It is the center object in React Native and the top-left corner in Skia. |
origin? | Point | Sets the origin of the transformation. This property is not inherited by its children. |
clip? | RectOrRRectOrPath | Rectangle, rounded rectangle, or Path to use to clip the children. |
invertClip? | boolean | Invert the clipping region: parts outside the clipping region will be shown and, inside will be hidden. |
layer? | RefObject<Paint> | Draws the children as a bitmap and applies the effects provided by the paint. |
The following three components are not being affected by the group properties. To apply paint effects on these component, you need to use layer effects. In each component reference, we also document how to apply paint effects on them.
Paint Properties
Its children will inherit all paint attributes applied to a group. These attributes can be properties like color
or style
or children like <Shader />
, or <ImageFilter />
for instance (see painting).
tsx
import {Canvas ,Circle ,Group } from "@shopify/react-native-skia";export constPaintDemo = () => {constr = 128;return (<Canvas style ={{flex : 1 }}><Circle cx ={r }cy ={r }r ={r }color ="#51AFED" />{/* The paint is inherited by the following sibling and descendants. */}<Group color ="lightblue"style ="stroke"strokeWidth ={10}><Circle cx ={r }cy ={r }r ={r / 2} /><Circle cx ={r }cy ={r }r ={r / 3}color ="white" /></Group ></Canvas >);};
tsx
import {Canvas ,Circle ,Group } from "@shopify/react-native-skia";export constPaintDemo = () => {constr = 128;return (<Canvas style ={{flex : 1 }}><Circle cx ={r }cy ={r }r ={r }color ="#51AFED" />{/* The paint is inherited by the following sibling and descendants. */}<Group color ="lightblue"style ="stroke"strokeWidth ={10}><Circle cx ={r }cy ={r }r ={r / 2} /><Circle cx ={r }cy ={r }r ={r / 3}color ="white" /></Group ></Canvas >);};
Transformations
The transform property is identical to its homonymous property in React Native except for one significant difference: in React Native, the origin of transformation is the center of the object, whereas it is the top-left position of the object in Skia.
The origin property is a helper to set the origin of the transformation. This property is not inherited by its children.
Simple Transformation
tsx
import {Canvas ,Fill ,Group ,RoundedRect } from "@shopify/react-native-skia";constSimpleTransform = () => {return (<Canvas style ={{flex : 1 }}><Fill color ="#e8f4f8" /><Group color ="lightblue"transform ={[{skewX :Math .PI / 6 }]}><RoundedRect x ={64}y ={64}width ={128}height ={128}r ={10} /></Group ></Canvas >);};
tsx
import {Canvas ,Fill ,Group ,RoundedRect } from "@shopify/react-native-skia";constSimpleTransform = () => {return (<Canvas style ={{flex : 1 }}><Fill color ="#e8f4f8" /><Group color ="lightblue"transform ={[{skewX :Math .PI / 6 }]}><RoundedRect x ={64}y ={64}width ={128}height ={128}r ={10} /></Group ></Canvas >);};
Transformation of Origin
tsx
import {Canvas ,Fill ,Group ,RoundedRect } from "@shopify/react-native-skia";constSimpleTransform = () => {return (<Canvas style ={{flex : 1 }}><Fill color ="#e8f4f8" /><Group color ="lightblue"origin ={{x : 128,y : 128 }}transform ={[{skewX :Math .PI / 6 }]}><RoundedRect x ={64}y ={64}width ={128}height ={128}r ={10} /></Group ></Canvas >);};
tsx
import {Canvas ,Fill ,Group ,RoundedRect } from "@shopify/react-native-skia";constSimpleTransform = () => {return (<Canvas style ={{flex : 1 }}><Fill color ="#e8f4f8" /><Group color ="lightblue"origin ={{x : 128,y : 128 }}transform ={[{skewX :Math .PI / 6 }]}><RoundedRect x ={64}y ={64}width ={128}height ={128}r ={10} /></Group ></Canvas >);};
Clipping Operations
clip
provides a clipping region that sets what part of the children should be shown.
Parts inside the region are shown, while those outside are hidden.
When using invertClip
, everything outside the clipping region will be shown, and parts inside the clipping region will be hidden.
Clip Rectangle
tsx
import {Canvas ,Group ,Image ,useImage ,rect ,Fill ,} from "@shopify/react-native-skia";constsize = 256;constpadding = 32;constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));constrct =rect (padding ,padding ,size -padding * 2,size -padding * 2);return (<Canvas style ={{flex : 1 }}><Fill color ="lightblue" /><Group clip ={rct }><Image image ={image }x ={0}y ={0}width ={size }height ={size }fit ="cover"/></Group ></Canvas >);};
tsx
import {Canvas ,Group ,Image ,useImage ,rect ,Fill ,} from "@shopify/react-native-skia";constsize = 256;constpadding = 32;constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));constrct =rect (padding ,padding ,size -padding * 2,size -padding * 2);return (<Canvas style ={{flex : 1 }}><Fill color ="lightblue" /><Group clip ={rct }><Image image ={image }x ={0}y ={0}width ={size }height ={size }fit ="cover"/></Group ></Canvas >);};
Clip Rounded Rectangle
tsx
import {Canvas ,Group ,Image ,useImage ,rrect ,rect ,} from "@shopify/react-native-skia";constsize = 256;constpadding = 32;constr = 8;constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));constroundedRect =rrect (rect (padding ,padding ,size -padding * 2,size -padding * 2),r ,r );return (<Canvas style ={{flex : 1 }}><Group clip ={roundedRect }><Image image ={image }x ={0}y ={0}width ={size }height ={size }fit ="cover"/></Group ></Canvas >);};
tsx
import {Canvas ,Group ,Image ,useImage ,rrect ,rect ,} from "@shopify/react-native-skia";constsize = 256;constpadding = 32;constr = 8;constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));constroundedRect =rrect (rect (padding ,padding ,size -padding * 2,size -padding * 2),r ,r );return (<Canvas style ={{flex : 1 }}><Group clip ={roundedRect }><Image image ={image }x ={0}y ={0}width ={size }height ={size }fit ="cover"/></Group ></Canvas >);};
Clip Path
tsx
import {Canvas ,Group ,Image ,useImage ,Skia ,} from "@shopify/react-native-skia";constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));conststar =Skia .Path .MakeFromSVGString ("M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z")!;return (<Canvas style ={{flex : 1 }}><Group clip ={star }><Image image ={image }x ={0}y ={0}width ={256}height ={256}fit ="cover" /></Group ></Canvas >);};
tsx
import {Canvas ,Group ,Image ,useImage ,Skia ,} from "@shopify/react-native-skia";constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));conststar =Skia .Path .MakeFromSVGString ("M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z")!;return (<Canvas style ={{flex : 1 }}><Group clip ={star }><Image image ={image }x ={0}y ={0}width ={256}height ={256}fit ="cover" /></Group ></Canvas >);};
Invert Clip
tsx
import {Canvas ,Group ,Image ,useImage ,Skia ,} from "@shopify/react-native-skia";constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));conststar =Skia .Path .MakeFromSVGString ("M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z")!;return (<Canvas style ={{flex : 1 }}><Group clip ={star }invertClip ><Image image ={image }x ={0}y ={0}width ={256}height ={256}fit ="cover" /></Group ></Canvas >);};
tsx
import {Canvas ,Group ,Image ,useImage ,Skia ,} from "@shopify/react-native-skia";constClip = () => {constimage =useImage (require ("./assets/oslo.jpg"));conststar =Skia .Path .MakeFromSVGString ("M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z")!;return (<Canvas style ={{flex : 1 }}><Group clip ={star }invertClip ><Image image ={image }x ={0}y ={0}width ={256}height ={256}fit ="cover" /></Group ></Canvas >);};
Layer Effects
Using the layer
property will create a bitmap drawing of the children.
You can use it to apply effects.
This is particularly useful to build effects that need to be applied to a group of elements and not one in particular.
tsx
import {Canvas ,Group ,Circle ,Blur ,Paint ,ColorMatrix ,} from "@shopify/react-native-skia";constClip = () => {return (<Canvas style ={{flex : 1 }}><Group color ="lightblue"layer ={<Paint ><Blur blur ={20} /><ColorMatrix matrix ={[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 18, -7,]}/></Paint >}><Circle cx ={0}cy ={128}r ={128 * 0.95} /><Circle cx ={256}cy ={128}r ={128 * 0.95} /></Group ></Canvas >);};
tsx
import {Canvas ,Group ,Circle ,Blur ,Paint ,ColorMatrix ,} from "@shopify/react-native-skia";constClip = () => {return (<Canvas style ={{flex : 1 }}><Group color ="lightblue"layer ={<Paint ><Blur blur ={20} /><ColorMatrix matrix ={[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 18, -7,]}/></Paint >}><Circle cx ={0}cy ={128}r ={128 * 0.95} /><Circle cx ={256}cy ={128}r ={128 * 0.95} /></Group ></Canvas >);};
Fitbox
The FitBox
component is based on the Group
component and allows you to scale drawings to fit into a destination rectangle automatically.
Name | Type | Description |
---|---|---|
src | SKRect | Bounding rectangle of the drawing before scaling |
dst | SKRect | Bounding rectangle of the drawing after scale |
fit? | Fit | Method to make the image fit into the rectangle. Value can be contain , fill , cover fitHeight , fitWidth , scaleDown , none (default is contain ) |
Example
Consider the following SVG export.
Its bounding source rectangle is 0, 0, 664, 308
:
xml
<svg width="664" height="308" viewBox="0 0 664 308" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M 170.1 215.5 C 165 222.3..." fill="black"/></svg>
xml
<svg width="664" height="308" viewBox="0 0 664 308" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M 170.1 215.5 C 165 222.3..." fill="black"/></svg>
We would like to automatically scale that path to our canvas of size 256 x 256
:
tsx
import {Canvas ,FitBox ,Path ,rect } from "@shopify/react-native-skia";constHello = () => {return (<Canvas style ={{width : 256,height : 256 }}><FitBox src ={rect (0, 0, 664, 308)}dst ={rect (0, 0, 256, 256)}><Path path ="M 170.1 215.5 C 165 222.3..."strokeCap ="round"strokeJoin ="round"style ="stroke"strokeWidth ={30}/></FitBox ></Canvas >);};
tsx
import {Canvas ,FitBox ,Path ,rect } from "@shopify/react-native-skia";constHello = () => {return (<Canvas style ={{width : 256,height : 256 }}><FitBox src ={rect (0, 0, 664, 308)}dst ={rect (0, 0, 256, 256)}><Path path ="M 170.1 215.5 C 165 222.3..."strokeCap ="round"strokeJoin ="round"style ="stroke"strokeWidth ={30}/></FitBox ></Canvas >);};