动画通常会增加应用程序或网站的视觉吸引力,并提高用户的整体参与度。根据 Forrester Research 的一项研究,拥有精心制作的动画的网站,用户参与度可提高高达 400%。引人入胜的动画可以吸引用户的注意力并鼓励他们与平台进行更多互动。然而,开发人员掌握动画有一个学习曲线,特别是在使用更先进的动画工具和技术时。
与其他动画工具或框架相比,对于没有动画经验的开发人员来说,掌握 Rive 相对容易。 Rive(以前称为 Flare)的设计宗旨是用户友好且可供开发人员使用,即使是那些之前很少或没有动画经验的人。在本文中,您将学习如何轻松创建简单、令人惊叹的 Rive 动画并在 Flutter 应用程序中管理它们。
Rive简介🧙♂️
一个简单的交互式登录动画🚀
结论🏋️♀️
参考资料🧶
Rive 是一款功能强大且用户友好的动画工具和运行时引擎,使开发人员和设计人员能够为各种平台(包括移动应用程序、Web 应用程序和游戏)创建令人惊叹的交互式动画。
以下是关键概念:
我们将完成创建一个简单的登录动画并将其导出到我们的 Flutter 应用程序的过程。我们将使用 StateMachine 来管理应用程序中该动画的交互性。最后应该是这样的👇🏽
请按照以下步骤在 Rive 画板上设置元素:
接下来,我们将绑住骨头并称重。绑定可确保当骨骼移动时,角色表面的相应部分也会相应移动,从而产生变形的错觉。加权也称为顶点加权,涉及根据角色网格的每个顶点与特定骨骼的接近程度为其分配影响值(权重)。我们将导航到要绑定的形状的路径。对于颈部,这就是我们将其绑定到颈骨的方式。
绑定骨骼后,我们通过为其分配权重来设置顶点。在这里,请注意,我们将最后一组顶点设置为 50%,因为我们希望两个骨骼对它们产生 50% 的效果。您应该使用 50%,尤其是当设置的顶点覆盖影响两个骨骼的部分时。现在,我们将对头发路径执行相同的操作。我们还将左右骨骼从一根骨头更改为两根骨头,以帮助我们实现头发所需的飘逸运动。
我们希望在这个动画中具有眨眼的效果,为了实现这一点,我们将在两个眼睛形状上使用剪辑功能,如下所示👇🏽
接下来,我们将使用平移约束向该元素添加头部跟踪,因为我们想要在动画期间移动头部。由于它是 2d 元素,因此添加平移约束将赋予其深度和某种形式的 3d 效果。选择所有内容并将其分组。现在我们只有一个组。
然后,在左上角,选择组工具并在头部中心(鼻子区域)创建一个组。在右侧工具栏上,将其样式从组更改为目标,将其命名为ctrl_front,复制它,并将重复的命名为ctrl_back。
对于目标 ctrl_back,从右侧工具栏中选择约束选项。从可用约束选项列表中选择平移约束。单击所选约束选项前面的图标以设置其属性。
将强度设置为-100并将其目标设置为ctrl front。现在,当您向前移动 ctrl 时,向后移动 ctrl 的方向相反。它将帮助我们对面部应向相反方向移动的部分(例如耳朵)设置约束。它应该看起来像这样👇🏽
现在我们将为脸部的其余部分设置约束。我们还将眼睛(左和右)和耳朵(左和右)分组,以帮助我们更好地管理它们。我们会给眼睛这样设置约束👇🏽
团体 | 约束强度 | 原点位置 | 目标 |
---|---|---|---|
眼镜 | 5% | 与 ctrl_front 原点相同 | ctrl_front |
眉毛 | 10% | 与 ctrl_front 原点相同 | ctrl_front |
耳朵 | 5% | 无需设置原点 | ctrl_返回 |
鼻子 | 5% | 与 ctrl_front 原点相同 | ctrl_front |
脸 | 5% | 与 ctrl_front 原点相同 | ctrl_front |
我们不需要为嘴唇设置限制。
这就是我们添加完所有约束后的样子👇🏽
💃🏽 🥳 恭喜,我们已经成功地为我们想要实现的动画类型准备好了元素。哇!!
单击右侧工具栏上的“动画”按钮,切换到动画界面。我们将创建六个动画时间线并将所有内容与状态机联系起来。在时间轴中,使用我们之前设置的骨骼和约束,我们可以设置关键帧来创建我们想要实现的动画。
第一个时间轴动画是空闲动画。这将是动画的空闲状态。当动画元素未参与时,我们将使用它。
对于这个空闲动画,我们将创建呼吸、轻微的头发移动和眨眼的幻觉。使用颈部骨骼、头发骨骼和右/左眼元素,我们将在不同的姿势中设置必要的关键帧,这意味着我们可以在时间轴上的点上设置所选项目的特定属性。考虑到从一个关键帧到下一关键帧的过渡样式,我们将选择我们需要的插值类型。您可以在时间轴部分右侧的底部找到它。插值可以是保持、线性或曲线,具体取决于您希望如何从一个关键帧移动到下一个关键帧。它会看起来像这样👇🏽
从上面的 gif 中,您可以注意到,在时间轴上的不同关键帧上,我们为所选项目设置了不同的姿势。从一个关键帧到另一关键帧的这种过渡形成了动画。使用相同的过程,我们将创建其他五个时间线。您可以单击此处观看此动画并详细查看不同的时间线。看起来像这样👇🏽
我们已经到了这个动画过程的最后部分。状态机是连接动画的视觉方式。使用状态机,我们可以根据我们设置的输入来控制播放哪个动画。我们可以混合或混合两个或多个时间线动画,以便它们同时播放。我们必须在状态机中选择正确的输入类型,因为这是我们将用来控制应用程序中的动画的输入。
在状态机中,我们有三种输入:
在“动画”面板上,单击加号按钮并创建一个状态机。我们将其命名为“登录状态机” 。这个名称很重要,因为这是我们稍后在代码中识别状态机所需要的。
请按照以下步骤设置您的状态机:
现在状态机中的完整动画将如下所示👇🏽
在这里查看完整的动画和状态机。
恭喜🥳,我们已经成功地为元素设置了动画并使用状态机对其进行了设置!但是,在导出 rive 文件之前,我们将更改背景和角色的衬衫颜色。它会看起来像这样👇🏽
背景颜色为(#B581EB),角色衬衫颜色为(#BD08D7)
这是动画的链接,可以查看所有详细信息
我们将在登录页面上使用此动画。创建 Flutter 应用项目并将 Rive 依赖项添加到pubspec.yaml
dependencies: rive: ^0.11.12
另外,将导出的 Rive 文件添加到您的项目资产中。现在我们可以继续根据我们的设计创建 UI。我们的目标是让动画执行以下操作:
我们将在 Widget Build 函数之前首先定义一些东西。
///Login details String emailCred = "[email protected]"; String passwordCred = "123456"; /// input form controller FocusNode emailFocusNode = FocusNode(); TextEditingController emailCtr = TextEditingController(); FocusNode passwordFocusNode = FocusNode(); TextEditingController passwordCtr = TextEditingController(); /// rive controller and input values StateMachineController? controller; SMIInput<bool>? check; SMIInput<double>? look; SMIInput<bool>? success; SMIInput<bool>? fail; bool isLoading = false; bool isError = false; @override void initState() { emailFocusNode.addListener(emailFocus); passwordFocusNode.addListener(passwordFocus); super.initState(); } @override void dispose() { emailFocusNode.removeListener(emailFocus); passwordFocusNode.removeListener(passwordFocus); super.dispose(); } void emailFocus() { check?.change(emailFocusNode.hasFocus); } void passwordFocus() { check?.change(passwordFocusNode.hasFocus); }
在这里,我们可以注意以下几点:
emailFocus
和passwordFocus
函数中,检查输入根据布尔值FocusNode.hasFocus
进行更改initState
和dispose
函数中,我们看到监听器被添加和删除。监听器用于监听焦点的变化。
您可以在此处查看 UI 代码和其余代码。这段代码展示了如何添加 RiveAsset:
SizedBox( height: 250, width: 250, child: RiveAnimation.asset( "assets/login_screen.riv", fit: BoxFit.fitHeight, stateMachines: const ["Login State Machine"], onInit: (artboard) { controller = StateMachineController.fromArtboard( artboard, "Login State Machine", ); if (controller == null) return; artboard.addController(controller!); check = controller?.findInput("check"); look = controller?.findInput("look"); success = controller?.findInput("success"); fail = controller?.findInput("fail"); }, ), ),
从上面的代码中,我们可以注意到以下几点:
下面是登录功能的代码:
void login()async{ //extract the text coming from the text fields final email = emailCtr.text; final password = passwordCtr.text; //Set loading boolean to true and delay to give an illusion of loading setState(() { isLoading = true; }); await Future.delayed( const Duration(milliseconds: 2000), ); // check if details entered is the same as the correct creditials defined if (email == emailCred && password == passwordCred) { //if correct trigger the success input and set error boolean to false success?.change(true); setState(() { isError = false; }); if(context.mounted){ // delay and navigate to home screen await Future.delayed( const Duration(seconds: 2),(){ Navigator.push(context, MaterialPageRoute(builder: (context) =>const HomeScreen())); }); } } else { // if details don't match defined credentials // set error boolean to true and trigger the fail input // set loading boolean to false setState(() { isError = true; }); fail?.change(true); } setState(() { isLoading = false; }); }
在这里查看完整的代码。
这样,我们就完成了登录动画代码。一切看起来是这样的:
恭喜!我们已经完成了这个简单的交互式登录动画。以下是我们能够完成的所有工作的概述:
逐步遵循本教程,您可能会遇到一些瓶颈,但通过练习会变得更容易。如果您在完成本教程时需要帮助,可以在Twitter上联系我或发表评论。
查看这些视频教程以更好地掌握 Rive 动画
您还可以查看Rive 频道,获取有关 Rive 动画的多个视频教程。
也发布在这里。