You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中Reanimated与Skia线性渐变动画失效求助

问题

尝试用React Native Reanimated和Skia实现线性渐变的颜色过渡动画,但动画完全无法运行,点击按钮触发过渡也没有效果。

使用版本:

  • react-native-skia: 1.7.6
  • react-native-reanimated: 3.16.0

相关代码:

export default function App() {
  const startColor = useSharedValue('rgb(255, 219, 128)');
  const endColor = useSharedValue('rgb(218, 78, 90)');
  const colors = useDerivedValue(() => {
    return [startColor.value, endColor.value];
  });
  const duration = 1000;
  const easing = Easing.bezier(0.25, -0.5, 0.25, 1);

  useEffect(() => {
    startColor.value = withRepeat(
      withTiming('rgb(255, 219, 128)', { duration, easing }),
      -1,
      true
    );
    endColor.value = withRepeat(
      withTiming('rgb(218, 78, 90)', { duration, easing }),
      -1,
      true
    );
  }, []);

  return (
    <View style={{flex: 1}}>
    <Canvas
      style={{
        flex: .6,
        justifyContent: 'center',
        alignItems: 'center'
      }}
    >
      <Rect x={50} y={150} width={300} height={300}>
        <LinearGradient
          start={vec(0, 0)}
          end={vec(300, 0)}
          colors={colors.value}
        />
      </Rect>
    </Canvas>
    </View>
  );
}

解决方案

问题根源

  1. Skia组件属性不支持直接监听共享值:React Native Skia的LinearGradient无法自动响应Reanimated共享值/派生值的变化,必须通过专门的动画化属性绑定来驱动更新。
  2. 字符串颜色的动画兼容性问题:Reanimated对数值类型的动画处理更稳定,字符串格式的RGB值可能无法被正确解析为可动画参数。
  3. 目标颜色配置错误:原代码中withTiming的目标颜色与初始值完全一致,导致没有视觉上的颜色过渡效果。

修复后的代码

import React, { useEffect } from 'react';
import { View, Button } from 'react-native';
import { Canvas, Rect, LinearGradient, vec } from '@shopify/react-native-skia';
import { useSharedValue, withRepeat, withTiming, Easing, useAnimatedProps } from 'react-native-reanimated';

export default function App() {
  // 用数值数组存储RGB通道值,提升动画精度
  const startColor = useSharedValue([255, 219, 128]);
  const endColor = useSharedValue([218, 78, 90]);
  const duration = 1000;
  const easing = Easing.bezier(0.25, -0.5, 0.25, 1);

  // 创建Skia可识别的动画化属性
  const animatedGradientProps = useAnimatedProps(() => ({
    colors: [
      `rgb(${startColor.value.join(',')})`,
      `rgb(${endColor.value.join(',')})`,
    ],
  }));

  // 自动触发动画
  useEffect(() => {
    startColor.value = withRepeat(
      withTiming([218, 78, 90], { duration, easing }),
      -1,
      true
    );
    endColor.value = withRepeat(
      withTiming([255, 219, 128], { duration, easing }),
      -1,
      true
    );
  }, []);

  // 按钮触发动画的回调
  const triggerAnimation = () => {
    startColor.value = withRepeat(
      withTiming([218, 78, 90], { duration, easing }),
      -1,
      true
    );
    endColor.value = withRepeat(
      withTiming([255, 219, 128], { duration, easing }),
      -1,
      true
    );
  };

  return (
    <View style={{ flex: 1, paddingTop: 50 }}>
      <Button title="触发颜色过渡" onPress={triggerAnimation} />
      <Canvas style={{ flex: 0.6, marginTop: 20 }}>
        <Rect x={50} y={150} width={300} height={300}>
          <LinearGradient
            start={vec(0, 0)}
            end={vec(300, 0)}
            animatedProps={animatedGradientProps}
          />
        </Rect>
      </Canvas>
    </View>
  );
}

关键修改说明

  • 颜色格式转换:将字符串RGB改为数值数组,让Reanimated能独立处理每个颜色通道的过渡动画,避免字符串解析问题。
  • 动画属性绑定:使用useAnimatedProps生成LinearGradient可识别的动态属性,确保组件能实时响应共享值变化。
  • 修正目标颜色:调整withTiming的目标值,实现两种颜色的双向循环过渡。
  • 移除无效样式:删除Canvas的justifyContent和alignItems,Canvas采用基于左上角的坐标系统,这些布局属性无效。

内容的提问来源于stack exchange,提问作者wind_kind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:12:37