动画
React Native Skia 提供了与 Reanimated v3 及以上版本的集成,从而可以在 UI 线程上执行动画。
React Native Skia 支持直接将 Reanimated 的共享值和派生值用作属性。 不需要像 createAnimatedComponent
或 useAnimatedProps
这样的函数;只需将 Reanimated 值直接作为属性传递即可。
tsx
import {useEffect } from "react";import {Canvas ,Circle ,Group } from "@shopify/react-native-skia";import {useDerivedValue ,useSharedValue ,withRepeat ,withTiming ,} from "react-native-reanimated";export constHelloWorld = () => {constsize = 256;constr =useSharedValue (0);constc =useDerivedValue (() =>size -r .value );useEffect (() => {r .value =withRepeat (withTiming (size * 0.33, {duration : 1000 }), -1);}, [r ,size ]);return (<Canvas style ={{flex : 1 }}><Group blendMode ="multiply"><Circle cx ={r }cy ={r }r ={r }color ="cyan" /><Circle cx ={c }cy ={r }r ={r }color ="magenta" /><Circle cx ={size /2}cy ={c }r ={r }color ="yellow"/></Group ></Canvas >);};
tsx
import {useEffect } from "react";import {Canvas ,Circle ,Group } from "@shopify/react-native-skia";import {useDerivedValue ,useSharedValue ,withRepeat ,withTiming ,} from "react-native-reanimated";export constHelloWorld = () => {constsize = 256;constr =useSharedValue (0);constc =useDerivedValue (() =>size -r .value );useEffect (() => {r .value =withRepeat (withTiming (size * 0.33, {duration : 1000 }), -1);}, [r ,size ]);return (<Canvas style ={{flex : 1 }}><Group blendMode ="multiply"><Circle cx ={r }cy ={r }r ={r }color ="cyan" /><Circle cx ={c }cy ={r }r ={r }color ="magenta" /><Circle cx ={size /2}cy ={c }r ={r }color ="yellow"/></Group ></Canvas >);};
我们提供了一些 Skia 特定的动画钩子,特别是针对路径的。
颜色
对于颜色,React Native Skia 使用与 Reanimated 不同的存储格式。这意味着 Reanimated 的 interpolateColor
无法直接使用。 相反,你可以使用 React Native Skia 的 interpolateColors
。
tsx
import {Canvas ,LinearGradient ,Fill ,// Use this function instead of interpolateColor from ReanimatedinterpolateColors ,vec ,} from "@shopify/react-native-skia";import {useEffect } from "react";import {useWindowDimensions } from "react-native";import {useDerivedValue ,useSharedValue ,withRepeat ,withTiming ,} from "react-native-reanimated";conststartColors = ["rgba(34, 193, 195, 0.4)","rgba(34,193,195,0.4)","rgba(63,94,251,1)","rgba(253,29,29,0.4)",];constendColors = ["rgba(0,212,255,0.4)","rgba(253,187,45,0.4)","rgba(252,70,107,1)","rgba(252,176,69,0.4)",];export constAnimatedGradient = () => {const {width ,height } =useWindowDimensions ();constcolorsIndex =useSharedValue (0);useEffect (() => {colorsIndex .value =withRepeat (withTiming (startColors .length - 1, {duration : 4000,}),-1,true);}, []);constgradientColors =useDerivedValue (() => {return [interpolateColors (colorsIndex .value , [0, 1, 2, 3],startColors ),interpolateColors (colorsIndex .value , [0, 1, 2, 3],endColors ),];});return (<Canvas style ={{flex : 1 }}><Fill ><LinearGradient start ={vec (0, 0)}end ={vec (width ,height )}colors ={gradientColors }/></Fill ></Canvas >);};
tsx
import {Canvas ,LinearGradient ,Fill ,// Use this function instead of interpolateColor from ReanimatedinterpolateColors ,vec ,} from "@shopify/react-native-skia";import {useEffect } from "react";import {useWindowDimensions } from "react-native";import {useDerivedValue ,useSharedValue ,withRepeat ,withTiming ,} from "react-native-reanimated";conststartColors = ["rgba(34, 193, 195, 0.4)","rgba(34,193,195,0.4)","rgba(63,94,251,1)","rgba(253,29,29,0.4)",];constendColors = ["rgba(0,212,255,0.4)","rgba(253,187,45,0.4)","rgba(252,70,107,1)","rgba(252,176,69,0.4)",];export constAnimatedGradient = () => {const {width ,height } =useWindowDimensions ();constcolorsIndex =useSharedValue (0);useEffect (() => {colorsIndex .value =withRepeat (withTiming (startColors .length - 1, {duration : 4000,}),-1,true);}, []);constgradientColors =useDerivedValue (() => {return [interpolateColors (colorsIndex .value , [0, 1, 2, 3],startColors ),interpolateColors (colorsIndex .value , [0, 1, 2, 3],endColors ),];});return (<Canvas style ={{flex : 1 }}><Fill ><LinearGradient start ={vec (0, 0)}end ={vec (width ,height )}colors ={gradientColors }/></Fill ></Canvas >);};