iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >react native reanimated实现动画示例详解
  • 820
分享到

react native reanimated实现动画示例详解

react native reanimated 动画react native reanimated 2023-03-06 11:03:20 820人浏览 薄情痞子
摘要

目录背景动画拆分实现抖动定义动画实现缩放动画改变内容Reanimated 原理浅析总结背景 在一次 App 迭代中,UI 想要给按钮添加一个动画效果,在对接的过程中,UI 表示直接

背景

在一次 App 迭代中,UI 想要给按钮添加一个动画效果,在对接的过程中,UI 表示直接用 .gif 就好,因为感觉开发出来的效果应该不会很好。

听到这里,一个技术人的自尊心仿佛被踩在了地上,我当即表示想用 React-native-reanimated(下文简称 Reanimated) 试一试。?

动画拆分

首先,从最外层来看,动画有一个抖动效果:先向左,再向右。可以利用 rotate 旋转属性来实现。

其次,中间的文字部分有一个缩放动画,可以通过 scale 实现。

最后,当文字最小化时,会改变内容,这个需要配合 js 来实现。

实现抖动

首先通过 useSharedValue 定义一个共享值 rotation,共享值和 useRef 类似,区别是共享值有一个 value 属性而不是 current

我们使用共享值改变的样式通过 useAnimatedStyle 包装一下,再赋值给 Animated.View,这和使用普通的 React Native 样式有点区别:

import Animated from 'react-native-reanimated';
const rotation = useSharedValue(0);
const shakeStyle = useAnimatedStyle(() => {
    return {
      transfORM: [
        {
          rotateZ: `${rotation.value}deg`,
        },
      ],
    };
  }, []);
<Animated.View style={[styles.btn, shakeStyle]}>
	...
</Animated.View>

定义动画

每个动画可以使用 withTiming 更新共享值,并设置动画的具体参数。它会启动基于时间的动画曲线,如执行时间 duration,缓动函数 easing 等。

抖动的过程有三个步骤:向左旋转,向右旋转,保持水平。我们使用 withSequence 来编排动画的顺序。

最后,我们使用 withRepeat 让以上三个步骤无限循环。它接受三个参数:

  • 第一参数是动画函数;
  • 第二个参数是执行的次数,-1 表示无限次;
  • 第三个参数表示动画是否反向执行。

注意,在恢复水平后,按钮仍保持一段时间的静止,我们可以用到 withDelay 来延迟执行下一个动作。

const SCOPE = 2;
useEffect(() => {
    const turnL = withDelay(1400, withTiming(-SCOPE, { duration: 100, easing: Easing.linear })); // 向左
    const turnR = withTiming(SCOPE, { duration: 100, easing: Easing.linear }); // 向右
    const holden = withTiming(0, { duration: 100, easing: Easing.linear }); // 水平
		const rotateAnimations = withSequence(turnL, turnR, holden); // 编排动画顺序
    rotation.value = withRepeat(rotateAnimations, -1); // 重复执行动画
    return () => {
      cancelAnimation(rotation);
    };
}, []);

实现缩放动画

实现缩放动画的思路与上面基本相似。这里需要注意的是,需要根据实际需求,调整动画之间的节奏关系。比如缩放开始,抖动开始;缩放结束,抖动也就结束。

const scaleSize = useSharedValue(0.2);
const scaleStyle = useAnimatedStyle(() => {
	return {
      transform: [
        {
          scale: scaleSize.value,
        },
      ],
	};
}, []);
useEffect(() => {
	...
	const zoomOut = withDelay(1600, withTiming(0.2, { duration: 100, easing: Easing.linear }));
	const restoreSize = withTiming(1, { duration: 100, easing: Easing.linear });
	const scaleAnimations = withSequence(restoreSize, zoomOut);
	scaleSize.value = withRepeat(scaleAnimations, -1);
	return () => {
		...
		cancelAnimation(scaleSize);
	};
}, [])
<Animated.View style={[styles.textWrapper, scaleStyle]}>
	...
<Animated.View>

改变内容

当我们依赖共享值的变化,需要进一步操作时,可以使用 useAnimatedReaction,它第一参数中定义依赖的值,第二个参数接受第一个参数的返回值,并进行自定义的操作。

注意,共享值变化不会触发 JS 线程中的组件更新,改变文案的状态需要用到 useState,因为文案改变是在 JS 线程中处理的,可以通过 runOnJS 可以让函数在 JS 线程中执行。

import { useAnimatedReaction, runOnJS } from 'react-native-reanimation'; 
...
const [status, setStatus] = useState(true);
const scaleSize = useSharedValue(0.2);
const toggle = useCallback(() => {
    setStatus((s) => !s);
}, []);
useAnimatedReaction(
    () => {
      return scaleSize.value;
    },
    (next) => {
      if (next <= 0.2) {
        runOnJS(toggle)();
      }
    }
);
...
<Text>{status ? '参与话题' : '赚点赞次数'}</Text>

Reanimated 原理浅析

在开发过程中,我们的动画代码和状态代码都是用 javascript 写在同一个文件中的,你可能会认为你写的动画部分的 JavaScript 和状态部分的 JavaScript 都是运行在同一个线程中的, 但其实并不是这样的。

React Native 有两个常用的线程:一个是 React Native 的 JavaScript 线程,另一个是 UI 主线程。

一方面,JavaScript 线程和 UI 主线程是异步通信的,这也意味着,如果是由 JavaScript 线程发起动画的执行,UI 线程并不能同步地收到该命令并且立刻执行。

另一方面,JavaScript 线程处理的事件很多,包括所有的业务逻辑、React Diff、事件响应等,容易抢占动画的执行资源。

Reanimated 是如何优化?答案就是:把动画代码放到 UI 主线程来执行性能更好、不易卡顿。

它把动画相关的 JavaScript 函数及其上下文传给了 UI 主线程。由于 UI 主线程没有能够运行 JavaScript 的环境,于是 Reanimated 又创建了一个 JavaScript 虚拟机来运行传过来的 JavaScript 函数。

在 JavaScript 线程中包括了三个动画相关的函数或值, useSharedValueuseAnimatedStyleuseAnimatedGestureHandler

这三部分的代码会在其底层,将相关的回调函数标记为worklet ,被标记的worklet函数或值会被放在一个由 Reanimated 创建的 JavaScript 虚拟机中执行。而这个由 Reanimated 创建的 JavaScript 虚拟机,会在 UI 线程中执行传过来的worklet 函数,并且执行的函数还可以同步地操作 UI。

Reanimated 动画性能好的原因就在于:React Native 的 JavaScript 线程是性能瓶颈点,而在真正执行动画时,已经把所有与动画相关 JavaScript 函数都放到了 UI 线程中独立的 JavaScript 虚拟机中了,并不会和 JavaScript 线程抢占硬件资源。

总结

Reanimated 处理动画的方法非常巧妙,并且性能极佳,是目前 React Native 社区中主流的动画处理方案,很多开源库都在使用。虽然官方文档有些缺陷,比如 api 没有 demo 不够直观、目前只有英文文档,对英文差的同学不够友好。

未来我们将深入学习和使用 Reanimated,来提升用户体验,实现媲美原生的交互效果。

以上就是react native reanimated实现动画示例详解的详细内容,更多关于react native reanimated 动画的资料请关注编程网其它相关文章!

--结束END--

本文标题: react native reanimated实现动画示例详解

本文链接: https://www.lsjlt.com/news/198654.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作