Values
React Native Skia supports Animations through the concept of Skia Values. A value can be seen as the state in the library where a change in will trigger a repaint request on the Canvas
component where it is used.
A simple example below shows how a value is used as a property for the x position of the Rect
element.
tsx
import {Canvas ,Rect ,useValue } from "@shopify/react-native-skia";import {useCallback } from "react";import {Button } from "react-native";constMyComponent = () => {constposition =useValue (0);constupdateValue =useCallback (() => (position .current =position .current + 10),[position ]);return (<><Canvas style ={{flex : 1 }}><Rect x ={position }y ={100}width ={10}height ={10}color ={"red"} /></Canvas ><Button title ="Move it"onPress ={updateValue } /></>);};
tsx
import {Canvas ,Rect ,useValue } from "@shopify/react-native-skia";import {useCallback } from "react";import {Button } from "react-native";constMyComponent = () => {constposition =useValue (0);constupdateValue =useCallback (() => (position .current =position .current + 10),[position ]);return (<><Canvas style ={{flex : 1 }}><Rect x ={position }y ={100}width ={10}height ={10}color ={"red"} /></Canvas ><Button title ="Move it"onPress ={updateValue } /></>);};
Skia Values
The basic SkiaValue
is a value that stores some kind of Javascript value. It can be used to store numbers, strings, booleans, objects and even arrays:
tsx
import {useValue } from "@shopify/react-native-skia";constprogress =useValue ({x : 100,y : 100 });constactualValue =progress .current ; // actualValue is now {x: 100, y: 100}
tsx
import {useValue } from "@shopify/react-native-skia";constprogress =useValue ({x : 100,y : 100 });constactualValue =progress .current ; // actualValue is now {x: 100, y: 100}
There are a few more value types in the library that will be described below.
Derived value
This value is a Skia Value that is derived from other Skia Values. It takes one or more existing values and a function that will calculate the new value based on the input. The function will be evaluated every time the input value changes.
tsx
import {useValue ,useDerivedValue } from "@shopify/react-native-skia";constradius =useValue (100);consttheta =useValue (Math .PI );constlength =useDerivedValue (() =>radius .current *theta .current , [radius ,theta ]);console .log (length .current ); // 314.1592653589793
tsx
import {useValue ,useDerivedValue } from "@shopify/react-native-skia";constradius =useValue (100);consttheta =useValue (Math .PI );constlength =useDerivedValue (() =>radius .current *theta .current , [radius ,theta ]);console .log (length .current ); // 314.1592653589793
Clock Value
This value is a value that updates on every display frame on the device. The value will be updated with the number of milliseconds elapsed since it was started.
tsx
import {useClockValue ,Canvas ,Circle ,useDerivedValue ,} from "@shopify/react-native-skia";constinterval = 3000;constDemo = () => {constclock =useClockValue ();constopacity =useDerivedValue (() => {return (clock .current %interval ) /interval ;},[clock ]);return (<Canvas style ={{flex : 1 }}><Circle r ={100}cx ={100}cy ={100}color ="black"opacity ={opacity } /></Canvas >);};
tsx
import {useClockValue ,Canvas ,Circle ,useDerivedValue ,} from "@shopify/react-native-skia";constinterval = 3000;constDemo = () => {constclock =useClockValue ();constopacity =useDerivedValue (() => {return (clock .current %interval ) /interval ;},[clock ]);return (<Canvas style ={{flex : 1 }}><Circle r ={100}cx ={100}cy ={100}color ="black"opacity ={opacity } /></Canvas >);};
Canvas
The useCanvas
hook returns a size
value that updates every time the canvas size updates.
On the first frame, the size is zero.
caution
useCanvas
can only be used inside the Canvas element because it relies on context.
tsx
importReact from "react";import {Canvas ,Fill ,Group ,Rect ,rect ,useCanvas ,useDerivedValue ,} from "@shopify/react-native-skia";constMyComp = () => {// 💚 useCanvasSize() can safely be used hereconst {size } =useCanvas ();// 💚 canvas is a regular skia value that can be used for animationsconstrct =useDerivedValue (() => {returnrect (0, 0,size .current .width ,size .current .height / 2);}, [size ]);return (<Group ><Fill color ="magenta" /><Rect color ="cyan"rect ={rct } />{/* ❌ this won't update since canvas is a skia value */}<Rect x ={0}y ={0}width ={size .current .width }height ={size .current .height /2}color ="red" /></Group >);};constExample = () => {// ❌ Using useCanvasSize() here would crashreturn (<Canvas style ={{flex : 1 }}><MyComp /></Canvas >);};
tsx
importReact from "react";import {Canvas ,Fill ,Group ,Rect ,rect ,useCanvas ,useDerivedValue ,} from "@shopify/react-native-skia";constMyComp = () => {// 💚 useCanvasSize() can safely be used hereconst {size } =useCanvas ();// 💚 canvas is a regular skia value that can be used for animationsconstrct =useDerivedValue (() => {returnrect (0, 0,size .current .width ,size .current .height / 2);}, [size ]);return (<Group ><Fill color ="magenta" /><Rect color ="cyan"rect ={rct } />{/* ❌ this won't update since canvas is a skia value */}<Rect x ={0}y ={0}width ={size .current .width }height ={size .current .height /2}color ="red" /></Group >);};constExample = () => {// ❌ Using useCanvasSize() here would crashreturn (<Canvas style ={{flex : 1 }}><MyComp /></Canvas >);};
Value Effect
The useValueEffect
hook allows you to execute change on value change.
In the example below we execute a callback on every frame (every time the clock value changes).
tsx
importReact , {useEffect } from "react";import {Animated } from "react-native";import {Canvas ,Rect ,mix ,useClockValue ,useValueEffect ,useValue ,interpolate } from "@shopify/react-native-skia";export constDemo = () => {constclock =useClockValue ();constx =useValue (0);useValueEffect (clock , () => {x .current =interpolate (clock .current , [0, 4000], [0, 200]);});return (<Canvas style ={{flex : 1 }}><Rect x ={x }y ={100}width ={10}height ={10}color ="red" /></Canvas >);};
tsx
importReact , {useEffect } from "react";import {Animated } from "react-native";import {Canvas ,Rect ,mix ,useClockValue ,useValueEffect ,useValue ,interpolate } from "@shopify/react-native-skia";export constDemo = () => {constclock =useClockValue ();constx =useValue (0);useValueEffect (clock , () => {x .current =interpolate (clock .current , [0, 4000], [0, 200]);});return (<Canvas style ={{flex : 1 }}><Rect x ={x }y ={100}width ={10}height ={10}color ="red" /></Canvas >);};