热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

flutteroffset_【译】Flutter中的花式背景动画

原文链接:https:medium.comfelixblaschkefancy-background-animations-in-flutter-4163d50f5c
原文链接:https://medium.com/@felixblaschke/fancy-background-animations-in-flutter-4163d50f5c37
本文主要介绍如何使用 simple_animations 实现漂亮的动画效果,Demo 可见 :gsy_flutter_demo

这篇文章将会介绍一个很有意思的动画效果,它能让 Flutter 的页面显得更加友好,同时本文也将展示如何使用 simple_animations 库,在 Flutter 上轻松地实现如下图所示的动画效果。

29a88fd74bed79d6ef3c0ebaee89ad73.gif

动画所需要展示的效果是:由平滑过渡的渐变背景组成,并且在文字下面会有多个波从右向左滑动。

接下来首先从背景渐变开始介绍,在 Flutter 中内置的 BoxDecoration 就支持使用 LinearGradient 来实现渐变效果,代码如下所示:

return Container(decoration: BoxDecoration(gradient: LinearGradient(begin: Alignment.topCenter,end: Alignment.bottomCenter,colors: [color1, color2])),
);

所以我们只需要在这个基础上去设置动画即可,这里直接使用 simple_animations 来实现效果, 在 simple_animations 中我们可以使用这两个对象来实现效果:

  • MultiTrackTween (动画处理对象,一次安排多个补间动画的属性)
  • ControlledAnimation(一个非常简单的基于补间动画的控件对象)

关于波形的实现在后面的文章中会介绍,这里先背景渐变的代码:

class AnimatedBackground extends StatelessWidget {@overrideWidget build(BuildContext context) {final tween = MultiTrackTween([Track("color1").add(Duration(seconds: 3),ColorTween(begin: Color(0xffD38312), end: Colors.lightBlue.shade900)),Track("color2").add(Duration(seconds: 3),ColorTween(begin: Color(0xffA83279), end: Colors.blue.shade600))]);return ControlledAnimation(playback: Playback.MIRROR,tween: tween,duration: tween.duration,builder: (context, animation) {return Container(decoration: BoxDecoration(gradient: LinearGradient(begin: Alignment.topCenter,end: Alignment.bottomCenter,colors: [animation["color1"], animation["color2"]])),);},);}
}

如上代码所示,在这里这里我们仅仅定义两个的 Track 的颜色 color1 和 color2,并将它设置到 ControlledAnimation 中,最后在 LinearGradient 使用这两个颜色。

是不是看起来很简单,这里甚至都没有看到任何 StatefulWidgetAnimationController,你可以将这段代码作为模板,并使用更复杂的颜色过渡对其进行扩展。

03d5aed79eb110d71fbc5047b57c2fb2.gif

现在我们有了一个渐变背景的动画,接着可以添加一些新的动画效果来完善效果,如下图所示是我们想要实现的最终效果:

443e55a2fe77c969999d23793ec25506.png

实际上,这是三个波型相互重叠的效果,这里我们需要确保它们彼此独立,以便于最终可以产生波纹的叠加效果。

因此,我们需要定义一个 WaveAnimation 具备以下属性的小控件:

  • speed:控制波浪动画的持续时间;
  • height:设置波浪作用的区域;
  • offset:x轴的偏移,以给出不同的波形“起始位置”;

接下来我们先要讨论一个数学的问题,要如何实现一个周期性的循环弧形动画效果呢?答案只有一个:三角函数

首先我们需要为动画设置一个 0.0 到 2 * pi 之间的值,并将该值放入到正弦函数中,接着我们在三个位置上采样 y 的数值大小:左侧、中间和末端。这样从左到右就覆盖了一个 pi 大小的间隔,因此我们始终可以看到一个完整的正弦波的一半。

我们为什么要采样三个位置?因为我们会根据这三个位置画一段 Path,如下图所示提供了这个可视化效果:

724c81c1e463fce9620637629ddce611.gif

我们从左上角开始(紫色),并在右上角(红色)添加一个二次贝塞尔函数连接过去,然后我们可以通过指定一个“控制点”(绿色)来实现这个变化,最后利用了 Flutter 的 Canvas 路径绘制的方法绘制出一个 Path

然后我们让红色的点往橙色移动,之后让紫色的点往黄色点以后,最后我们只需要把这个 Path 路径给连接起来就可以了。

当你只仅关注紫色、绿色和红色点的时候,就可以看到我们的采样后的路径是一个正弦波的效果。

这个二次贝塞尔函数乍一看似乎有些诡异,但是它只是想画一条从紫色到红色的直线(蓝色)。它和绿点之间的距离越长,线条就会受到某种类似重力因素的影响得到灰色的形状,最终的结果是线逐渐弯曲。

class AnimatedWave extends StatelessWidget {final double height;final double speed;final double offset;AnimatedWave({this.height, this.speed, this.offset = 0.0});@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (context, constraints) {return Container(height: height,width: constraints.biggest.width,child: ControlledAnimation(playback: Playback.LOOP,duration: Duration(milliseconds: (5000 / speed).round()),tween: Tween(begin: 0.0, end: 2 * pi),builder: (context, value) {return CustomPaint(foregroundPainter: CurvePainter(value + offset),);}),);});}
}class CurvePainter extends CustomPainter {final double value;CurvePainter(this.value);@overridevoid paint(Canvas canvas, Size size) {final white = Paint()..color = Colors.white.withAlpha(60);final path = Path();final y1 = sin(value);final y2 = sin(value + pi / 2);final y3 = sin(value + pi);final startPointY = size.height * (0.5 + 0.4 * y1);final controlPointY = size.height * (0.5 + 0.4 * y2);final endPointY = size.height * (0.5 + 0.4 * y3);path.moveTo(size.width * 0, startPointY);path.quadraticBezierTo(size.width * 0.5, controlPointY, size.width, endPointY);path.lineTo(size.width, size.height);path.lineTo(0, size.height);path.close();canvas.drawPath(path, white);}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}

对于这个控件,我们使用了一个 LayoutBuilder 来检查可用的宽度再进行绘制,然后使用 ControlledAnimationPlayback.LOOP 实现从 0.0 到 2 * pi 的简单补间数据,之后可以将当前动画值传递到 CustomPainterCanvas 进行动画绘制。

最终这个 CustomPainter 可以实现我们想要的波形路径,但需要注意的是,我们使用的波形与不透明度需要一层层减小,这样多个波始重叠才能始终可见。

是不是用相当少的代码就实现了很炫酷的动画?

最后如下代码所示,我们使用 Stack 将控件堆叠在一起。

class FancyBackgroundApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return Stack(children: [Positioned.fill(child: AnimatedBackground()),onBottom(AnimatedWave(height: 180,speed: 1.0,)),onBottom(AnimatedWave(height: 120,speed: 0.9,offset: pi,)),onBottom(AnimatedWave(height: 220,speed: 1.2,offset: pi / 2,)),Positioned.fill(child: CenteredText()),],);}onBottom(Widget child) => Positioned.fill(child: Align(alignment: Alignment.bottomCenter,child: child,),);
}

b3f5437f93b93c4ac0ed9c273453cd2e.png

Flutter 文章汇总地址:

Flutter 完整实战实战系列文章专栏
Flutter 番外的世界系列文章专栏

资源推荐

  • 本文 Demo 可见 :gsy_flutter_demo/anim_bg_demo_page.dart
  • Github : https://github.com/CarGuo
  • 开源 Flutter 完整项目:https://github.com/CarGuo/GSYGithubAppFlutter
  • 开源 Flutter 多案例学习型项目: https://github.com/CarGuo/GSYFlutterDemo
  • 开源 Fluttre 实战电子书项目:https://github.com/CarGuo/GSYFlutterBook
  • 开源 React Native 项目:https://github.com/CarGuo/GSYGithubApp



推荐阅读
  • 在 Flutter 开发过程中,开发者经常会遇到 Widget 构造函数中的可选参数 Key。对于初学者来说,理解 Key 的作用和使用场景可能是一个挑战。本文将详细探讨 Key 的概念及其应用场景,并通过实例帮助你更好地掌握这一重要工具。 ... [详细]
  • 本文介绍了如何在 Flutter 应用程序中使用单例模式创建一个全局唯一的数据管理类,以确保在整个应用生命周期中数据的一致性和可访问性。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 本文探讨了在使用Azure Active Directory进行用户身份验证时,结合AddAuthentication和RequireAuthenticatedUser的必要性及其潜在冗余问题。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • Microsoft即将发布WPF/E的CTP(Community Technology Preview)和SDK,标志着RIA(Rich Internet Application)技术的新里程碑。更多详情及下载链接请参见MSDN官方页面。 ... [详细]
  • 本文探讨了在 Flutter 应用开发中,使用 runApp(new MyApp()) 和 runApp(new MaterialApp()) 之间的主要区别,特别是它们对热重载行为的影响。 ... [详细]
  • Flutter入门指南:实现自动关闭的对话框与提示
    本文为Flutter系列教程的一部分,专注于讲解如何在Flutter应用中实现自动关闭的对话框和提示。通过具体的代码示例,帮助开发者掌握SnackBar、BottomSheet和Dialog的使用方法。 ... [详细]
  • Flutter 高德地图插件使用指南
    本文档详细介绍了如何在Flutter项目中集成和使用高德地图插件,包括安装、配置及基本使用方法。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 探讨了小型企业在构建安全网络和软件时所面临的挑战和机遇。本文介绍了如何通过合理的方法和工具,确保小型企业能够有效提升其软件的安全性,从而保护客户数据并增强市场竞争力。 ... [详细]
  • Vue 3.0 翻牌数字组件使用指南
    本文详细介绍了如何在 Vue 3.0 中使用翻牌数字组件,包括其基本设置和高级配置,旨在帮助开发者快速掌握并应用这一动态视觉效果。 ... [详细]
  • 前言Git是目前最流行的版本控制系统,在它的基础之上,GitHub和GitLab成为当前最流行的代码托管平台,它们均提供的代码评审、项目管理、持续集成等功能,越来越多的互联网企业都 ... [详细]
  • 本文提供了详细的步骤,指导如何在Ubuntu系统中配置ASOP源码的编译环境,特别强调了使用国内镜像加速下载过程的方法。若遇到文章加载问题或图片失效,建议访问原文链接获取最新信息。 ... [详细]
author-avatar
丿艹约锭So灬幸福老师
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有