paint-brush
Rive Animation for Flutter:轻松构建令人惊叹的动画的初学者指南!经过@nikkieke
736 讀數
736 讀數

Rive Animation for Flutter:轻松构建令人惊叹的动画的初学者指南!

经过 17m2023/08/20
Read on Terminal Reader

太長; 讀書

与其他动画工具或框架相比,对于没有动画经验的开发人员来说,掌握 Rive 相对容易。 Rive(以前称为 Flare)的设计宗旨是用户友好且可供开发人员使用,即使是那些之前很少或没有动画经验的人。在本文中,您将学习如何轻松创建简单、令人惊叹的 Rive 动画并在 Flutter 应用程序中管理它们。
featured image - Rive Animation for Flutter:轻松构建令人惊叹的动画的初学者指南!
undefined HackerNoon profile picture
0-item
1-item

动画通常会增加应用程序或网站的视觉吸引力,并提高用户的整体参与度。根据 Forrester Research 的一项研究,拥有精心制作的动画的网站,用户参与度可提高高达 400%。引人入胜的动画可以吸引用户的注意力并鼓励他们与平台进行更多互动。然而,开发人员掌握动画有一个学习曲线,特别是在使用更先进的动画工具和技术时。


与其他动画工具或框架相比,对于没有动画经验的开发人员来说,掌握 Rive 相对容易。 Rive(以前称为 Flare)的设计宗旨是用户友好且可供开发人员使用,即使是那些之前很少或没有动画经验的人。在本文中,您将学习如何轻松创建简单、令人惊叹的 Rive 动画并在 Flutter 应用程序中管理它们。

目录

  • Rive简介🧙‍♂️

    • Rive 中的基本概念🧗
  • 一个简单的交互式登录动画🚀

    • 在画板上设置元素📃
    • 动画时间!🕶️
    • 设置你的状态机🏍️
    • 在 Flutter 应用程序中实现动画👨‍🚒
  • 结论🏋️‍♀️

  • 参考资料🧶



Rive简介🧙‍♂️

Rive 是一款功能强大且用户友好的动画工具和运行时引擎,使开发人员和设计人员能够为各种平台(包括移动应用程序、Web 应用程序和游戏)创建令人惊叹的交互式动画。

Rive 中的基本概念🧗

以下是关键概念:


  1. 画板:画板是您创建动画的画布。它是创建和组织动画元素(例如组、约束、骨骼等)的主要场所。
  2. 时间轴:时间轴是定义动画的地方。它允许您设置关键帧并指定对象应如何随时间变化。关键帧表示明确定义对象属性的特定时间点。动画系统在关键帧之间进行插值以创建平滑的过渡。
  3. 状态机: Rive 具有状态机功能,允许您为动画指定不同的状态。您可以根据用户输入或其他条件触发状态转换,从而能够根据当前状态创建具有不同行为的交互式动画。
  4. 代码导出: Rive 允许您将动画导出为代码,这样可以轻松地将它们集成到您的应用程序中。对于 Flutter 开发人员,Rive 提供了 Flutter 运行时和集成包,方便在 Flutter 项目中使用 Rive 动画。

一个简单的交互式登录动画🚀

我们将完成创建一个简单的登录动画并将其导出到我们的 Flutter 应用程序的过程。我们将使用 StateMachine 来管理应用程序中该动画的交互性。最后应该是这样的👇🏽

Flutter App 中完整的 Rive 动画

在画板上设置元素📃

请按照以下步骤在 Rive 画板上设置元素:

  • 首先,我们需要获取元素本身。我从 Figma 上的用户角色插图模板中获得它。将元素导出为 SVG 文件。
  • 转到Rive单击“开始”按钮打开您的草稿
  • 在草稿中,创建一个新文件并选择一个空白画板。
  • 将元素拖放到画板上,它会自动添加到资源文件夹中,您可以看到它放置在画板上,它应该看起来像这样👇🏽

画板上的图像

  • 在侧边栏上,我们将对构成该元素的不同形状进行分组并相应地命名它们。使用Ctrl 或 Ctrl + shift选择要分组的所有内容。选择它后,使用Ctrl + G将它们分组。它应该看起来像这样👇🏽

元素的分组形状

  • 现在我们将向该元素添加骨骼。骨骼有助于创建更加动态和逼真的动画。考虑到我们希望这个动画的效果,我们将在颈部和胸部添加骨骼以创建呼吸的错觉。我们还将在头发上添加骨骼,因为我们希望头发也能稍微移动。
  • 选择左上角的骨骼工具或使用Ctrl + B 。添加骨头后,应该是这样的👇🏽

添加骨头

  • 现在我们将重命名骨骼以便于识别。我们还将对面部的所有元素进行分组,并将这个新组命名为face 。使用层次关系,我们可以将骨骼连接到我们需要影响或变形的元素部分。我们可以通过将骨骼移动到它们直接影响的形状来做到这一点。要移动组或骨骼,请使用鼠标选择并移动它。它会看起来像这样👇🏽

骨骼的等级关系

  • 接下来,我们将绑住骨头并称重。绑定可确保当骨骼移动时,角色表面的相应部分也会相应移动,从而产生变形的错觉。加权也称为顶点加权,涉及根据角色网格的每个顶点与特定骨骼的接近程度为其分配影响值(权重)。我们将导航到要绑定的形状的路径。对于颈部,这就是我们将其绑定到颈骨的方式。

    绑扎并称重骨头

    绑定骨骼后,我们通过为其分配权重来设置顶点。在这里,请注意,我们将最后一组顶点设置为 50%,因为我们希望两个骨骼对它们产生 50% 的效果。您应该使用 50%,尤其是当设置的顶点覆盖影响两个骨骼的部分时。现在,我们将对头发路径执行相同的操作。我们还将左右骨骼从一根骨头更改为两根骨头,以帮助我们实现头发所需的飘逸运动。

  • 我们希望在这个动画中具有眨眼的效果,为了实现这一点,我们将在两个眼睛形状上使用剪辑功能,如下所示👇🏽

使用剪辑功能实现闪烁效果

  • 接下来,我们将使用平移约束向该元素添加头部跟踪,因为我们想要在动画期间移动头部。由于它是 2d 元素,因此添加平移约束将赋予其深度和某种形式的 3d 效果。选择所有内容并将其分组。现在我们只有一个组。

  • 然后,在左上角,选择组工具并在头部中心(鼻子区域)创建一个组。在右侧工具栏上,将其样式从组更改为目标,将其命名为ctrl_front,复制它,并将重复的命名为ctrl_back。

  • 对于目标 ctrl_back,从右侧工具栏中选择约束选项。从可用约束选项列表中选择平移约束。单击所选约束选项前面的图标以设置其属性。

  • 将强度设置为-100并将其目标设置为ctrl front。现在,当您向前移动 ctrl 时,向后移动 ctrl 的方向相反。它将帮助我们对面部应向相反方向移动的部分(例如耳朵)设置约束。它应该看起来像这样👇🏽


    添加目标

  • 现在我们将为脸部的其余部分设置约束。我们还将眼睛(左和右)和耳朵(左和右)分组,以帮助我们更好地管理它们。我们会给眼睛这样设置约束👇🏽

为眼睛设置约束

  • 请注意我们如何首先将眼睛组的原点设置为与ctrl_front的原点相同。这样,当我们移动ctrl_front目标时,现在受限于该目标的眼睛组将随之移动,而不会笨拙地跳来跳去。我们将对以下内容做同样的事情:

团体

约束强度

原点位置

目标

眼镜

5%

与 ctrl_front 原点相同

ctrl_front

眉毛

10%

与 ctrl_front 原点相同

ctrl_front

耳朵

5%

无需设置原点

ctrl_返回

鼻子

5%

与 ctrl_front 原点相同

ctrl_front

5%

与 ctrl_front 原点相同

ctrl_front


我们不需要为嘴唇设置限制。


这就是我们添加完所有约束后的样子👇🏽




添加了所有约束

💃🏽 🥳 恭喜,我们已经成功地为我们想要实现的动画类型准备好了元素。哇!!

动画时间!🕶️

单击右侧工具栏上的“动画”按钮,切换到动画界面。我们将创建六个动画时间线并将所有内容与状态机联系起来。在时间轴中,使用我们之前设置的骨骼和约束,我们可以设置关键帧来创建我们想要实现的动画。


第一个时间轴动画是空闲动画。这将是动画的空闲状态。当动画元素未参与时,我们将使用它。

  • 首先,在开始动画过程之前,我们将元素的所有部分分组并命名为角色。
  • 然后我们将持续时间设置为4分钟,
  • 设置我们的工作区,并将时间线类型设置为循环。它非常适合闲置动画。


对于这个空闲动画,我们将创建呼吸、轻微的头发移动和眨眼的幻觉。使用颈部骨骼、头发骨骼和右/左眼元素,我们将在不同的姿势中设置必要的关键帧,这意味着我们可以在时间轴上的点上设置所选项目的特定属性。考虑到从一个关键帧到下一关键帧的过渡样式,我们将选择我们需要的插值类型。您可以在时间轴部分右侧的底部找到它。插值可以是保持、线性或曲线,具体取决于您希望如何从一个关键帧移动到下一个关键帧。它会看起来像这样👇🏽

空闲动画

从上面的 gif 中,您可以注意到,在时间轴上的不同关键帧上,我们为所选项目设置了不同的姿势。从一个关键帧到另一关键帧的这种过渡形成了动画。使用相同的过程,我们将创建其他五个时间线。您可以单击此处观看此动画并详细查看不同的时间线。看起来像这样👇🏽

设置你的状态机🏍️

我们已经到了这个动画过程的最后部分。状态机是连接动画的视觉方式。使用状态机,我们可以根据我们设置的输入来控制播放哪个动画。我们可以混合或混合两个或多个时间线动画,以便它们同时播放。我们必须在状态机中选择正确的输入类型,因为这是我们将用来控制应用程序中的动画的输入。


在状态机中,我们有三种输入:

  • 数字:数字输入是状态机中用于表示和控制定量数据的数值。您可以将状态机设置为根据数字输入数值转换到特定状态。
  • 布尔值:布尔值输入是一个二进制值,可以是 true 或 false。现在,状态机根据输入值(真或假)转换到特定状态。
  • 触发器:触发输入是用于发出事件信号的输入。与在显式更改之前保持其状态的布尔输入不同,触发器在触发后重置为其默认状态。


在“动画”面板上,单击加号按钮并创建一个状态机。我们将其命名为“登录状态机” 。这个名称很重要,因为这是我们稍后在代码中识别状态机所需要的。


请按照以下步骤设置您的状态机:

  1. 在我们的状态机中创建两层并将其中一层重命名为Type 。多层帮助我们同时玩多个状态。要在状态机中获取另一个层,请单击状态机图顶部的加号图标。
  2. 在“输入”部分,您应该会在状态机旁边看到它的标签。单击加号图标,选择一个数字输入,并将其命名为Look 。我们将在混合(混合) look_leftlook_right时间轴动画时使用此输入,以便随着数字的增加,角色看起来像是从左向右看。
  3. 创建另一个输入,这次是布尔值,并将其命名为 check 。它控制我们希望动画何时显示。创建两个触发器输入,将其中一个重命名为failed ,另一个重命名为success 。您将需要它来触发成功和失败状态。
  4. 现在将look_idle动画和look_left动画拖放到Type图层图上。在此图表中,您将看到一些默认状态:
    • Entry - 这是连接到该状态的任何动画状态的入口点。
    • Exit - 这是连接到该状态的任何动画状态的退出点
    • Anystate - 只要满足转换中的条件,就会播放与此连接的任何动画状态。
  5. 转换是连接两个或多个状态的线和箭头。查看箭头方向,您可以看到状态现在是如何连接的。当您单击此按钮时,您可以看到过渡的属性。在属性中,您可以创建条件。使用您之前创建的任何输入,您可以定义您希望在转换中的下一个状态之前必须满足的条件
  6. 类型层中,使用转换线性连接EntryLook_IdleLook_left状态。对于look_left状态,我们希望它是look_leftlook_right动画的混合。为此,请选择图形上的look_left状态,然后在面板的左侧选择Blend 1d。对于输入选项,选择外观输入。该输入将控制我们的混合。然后在“Timelines”部分中,选择“look_left ”和“look_right”时间线,并将它们设置为 0 和 100。当您增加外观输入图时,它会混合两个动画。
  7. 使用过渡线和箭头将混合状态连接到look_idle 。现在单击箭头并将条件设置为检查输入为 false 时。它将帮助我们控制动画并告诉StateMachine,当检查布尔值为假时显示look_idle状态。对从look_idle指向混合状态的转换箭头执行相同的操作,但现在检查布尔值是否设置为true。
  8. 现在,当您单击检查输入的复选框时,可以将其设置为 true 或 false。当您播放状态机时,它会一直显示look_Idle状态,直到您将检查布尔值更改为true,然后它将开始look_left动画。要混合look_leftlook_right ,您可以增加Look输入数值。
  9. 现在,在 Layer1 中,您将在此处添加成功失败触发器。从进入状态开始,将连接到空闲状态。从空闲状态连接成功失败状态。在从idle状态到success状态的转换中,添加一个条件。在此情况下,添加成功触发输入。也就是说,只有当成功输入被触发时,状态机才应该播放成功动画。
  10. 失败状态转换执行相同的操作,但在条件中添加失败触发器。现在,从成功开始,创建一条返回空闲状态的转换线。这里选择退出时间,并将其设置为100%。这意味着只有当成功动画播放完毕后才会播放空闲动画。对故障恢复到空闲转换执行相同的操作。


现在状态机中的完整动画将如下所示👇🏽

状态机上的完整动画

在这里查看完整的动画和状态机。


恭喜🥳,我们已经成功地为元素设置了动画并使用状态机对其进行了设置!但是,在导出 rive 文件之前,我们将更改背景和角色的衬衫颜色。它会看起来像这样👇🏽

不同背景颜色的字符

背景颜色为(#B581EB),角色衬衫颜色为(#BD08D7)


这是动画的链接,可以查看所有详细信息

在 Flutter 应用程序中实现动画👨‍🚒

我们将在登录页面上使用此动画。创建 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); }

在这里,我们可以注意以下几点:

  • 已定义正确的电子邮件和密码。
  • 还定义了电子邮件和密码的焦点节点和文本编辑控制器。
  • 这里 Rive 控制器和输入被定义为可为空。您会注意到,输入是使用它们在状态机中使用的确切名称来定义的。
  • 定义了加载和错误布尔值。
  • emailFocuspasswordFocus函数中,检查输入根据布尔值FocusNode.hasFocus进行更改
  • 然后在initStatedispose函数中,我们看到监听器被添加和删除。监听器用于监听焦点的变化。


您可以在此处查看 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"); }, ), ),

从上面的代码中,我们可以注意到以下几点:

  • StateMachine 的名称与我们在 Rive 编辑器中命名的名称相同
  • 控制器和输入被定义


下面是登录功能的代码:

 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; }); }

在这里查看完整的代码。


这样,我们就完成了登录动画代码。一切看起来是这样的:

flutter 应用程序中完整的 rive 动画

结论🏋️‍♀️

恭喜!我们已经完成了这个简单的交互式登录动画。以下是我们能够完成的所有工作的概述:

  • 在 Rive 画板上设置我们的元素,
  • 创建该元素的不同动画状态,
  • 在状态机的帮助下将所有这些状态放在一起
  • 导出并将其添加到 Flutter 应用程序中


逐步遵循本教程,您可能会遇到一些瓶颈,但通过练习会变得更容易。如果您在完成本教程时需要帮助,可以在Twitter上联系我或发表评论。


查看这些视频教程以更好地掌握 Rive 动画




您还可以查看Rive 频道,获取有关 Rive 动画的多个视频教程。

参考资料🧶

动画登录角色


也发布在这里