美文网首页
react-native-reanimated系列(三)

react-native-reanimated系列(三)

作者: 十豆三撇 | 来源:发表于2021-03-27 12:21 被阅读0次

    react-native-reanimated系列(一)
    react-native-reanimated系列(二)

    Shared Values

    作用:携带可动画的数据,提供响应式和驱动式动画。

    携带数据

    特点一:共享内存,数据可以在线程间安全地读取和修改。
    特点二:共享数据必须通过对象的.value属性来访问和修改。
    特点三:从UI线程执行的读写操作都是同步的,在React Native JS线程上进行的更新都是异步的。

    • 从React Native JS线程异步更新值
    import { useSharedValue } from 'react-native-reanimated';
    
    function SomeComponent() {
      const sharedVal = useSharedValue(0);
      return (
        <Button
          onPress={() => (sharedVal.value = Math.random())}
          title="Randomize"
        />
      );
    }
    
    • 使用worklet同步更新值
    import Animated, { useSharedValue, useAnimatedScrollHandler } from 'react-native-reanimated';
    
    function SomeComponent({ children }) {
    
      const scrollOffset = useSharedValue(0);
    
      const scrollHandler = useAnimatedScrollHandler({
        onScroll: event => {
          scrollOffset.value = event.contentOffset.y;
        },
      });
    
      return (
        <Animated.ScrollView onScroll={scrollHandler}>
          {children}
        </Animated.ScrollView>
      );
    }
    

    上面的例子中,srcoll handler就是一个worklet,并在UI线程上运行滚动事件逻辑。在该worklet中进行的更新是同步的。

    响应性

    对Shared Values的更新可以触发UI线程上相应的代码执行,从而导致启动动画、视图更新等。
    当前有两种方法可以创建响应式的worklet,分别是useAnimatedStyleuseDerivedValue钩子。

    import Animated, { useSharedValue, useAnimatedStyle } from 'react-native-reanimated';
    
    function Box() {
      const offset = useSharedValue(0);
    
      const animatedStyles = useAnimatedStyle(() => {
        return {
          transform: [{ translateX: offset.value * 255 }],
        };
      });
    
      return (
        <>
          <Animated.View style={[styles.box, animatedStyles]} />
          <Button onPress={() => (offset.value = Math.random())} title="Move" />
        </>
      );
    }
    
    sample01.gif

    驱动动画

    Reanimated库内置了许多帮助运行和自定义动画的方法。启动动画的方式之一是对Shared Value开始动画过渡。

    import { withTiming } from 'react-native-reanimated';
    
    someSharedValue.value = withTiming(50);
    

    在上面的代码中,偏移共享值,而不是立即设置为50,将使用基于时间的动画从当前值转换为50。

    import Animated, { withSpring } from 'react-native-reanimated';
    
    function Box() {
      const offset = useSharedValue(0);
    
      const animatedStyles = useAnimatedStyle(() => {
        return {
          transform: [{ translateX: offset.value * 255 }],
        };
      });
    
      return (
        <>
          <Animated.View style={[styles.box, animatedStyles]} />
          <Button
            onPress={() => {
              offset.value = withSpring(Math.random());
            }}
            title="Move"
          />
        </>
      );
    }
    

    在上面的代码中,使用withSpring更新偏移量,将弹性的从当前值转换为更新值。因此,更新视图的移动动画将会变得平滑。

    动画进度

    开始Shared Value过渡动画后,.value属性将与动画进度同步。也就是说,当初始值为0时,使用withTiming(50)开始动画过渡,默认耗时300ms,期望.value属性的读取值返回一个从0到50的数字,该数字将对应当前位置作为动画进度。

    中断动画

    由于Shared Value会保持其动画过渡的状态,因此我们可以使所有的动画完全中断。这意味着即使Shared Value当前正在运行动画,您也可以对其进行更新,而不必担心这会导致意外和突然的动画故障。在这种情况下覆盖该值将导致先前的动画被中断。如果新分配的值是一个数字(或任何静态值),则该新值将立即分配给Shared Value,并且先前运行的动画将被取消。如果新分配的值也是动画,则先前运行的动画将平滑过渡到新动画。诸如速度之类的动画参数也会这样平滑过渡,这在基于弹簧的动画中尤为重要。这样可以实现从一种动画到另一种动画的真正平滑的转换。


    sample02.gif

    取消动画

    在某些情况下,我们希望停止当前正在运行的动画而不启动新动画。在Reanimated中,可以使用cancelAnimation方法。

    import { cancelAnimation } from 'react-native-reanimated'
    
    cancelAnimation(someSharedValue);
    

    从UI线程和React Native的JS线程中取消动画均可。

    Shared Values与Animated.Value比较

    特性 Animated Value Shared Value
    携带数据类型 仅支持数字和字符串 任何原始或嵌套的数据结构(例如对象,数组,字符串,数字,布尔值)
    关联视图属性 通过直接传递Animated.Value作为属性 不能直接与视图的属性关联,应该使用useAnimatedStyleuseAnimatedProps
    更新值 使用value.setValue方法(当使用native driver时,更新就是异步调用) 直接更新.value属性(UI线程同步更新,React Native JS线程异步更新)
    读取值 通过value.addListener注册监听来获取所有动画值更新 直接读取.value属性
    运行动画 使用Animated.springAnimated.timing(或其他),将Animated Value作为参数传递,并运行.start()方法以启动动画 更新.value属性,同时使用动画方法(例如withTiming)包装
    停止动画 通过Animated.timing(或其他)返回动画对象的引用,并让它调用stopAnimation()方法 把Shared Value作为参数传递给cancelAnimation方法
    插值 使用Animated Value的interpolate()成员方法 使用interpolate方法,如果需要跟踪值,则可以将其与useDerivedValue一起使用

    相关文章

      网友评论

          本文标题:react-native-reanimated系列(三)

          本文链接:https://www.haomeiwen.com/subject/raodhltx.html