Flutter实现笑嘻嘻的动态表情的示例代码

目录
  • 前言
  • AnimatedContainer 介绍
  • 组件结构
  • 细节实现
  • 总结

前言

身在孤岛有很多无奈,比如说程序员属于比较偏门的职业。尤其是早些年,在行业里跳过几次槽后,可能你就已经认识整个圈子的人了。然后,再跳槽很可能就再次“偶遇”前同事了,用大潘的口头语来说就是:“好尴尬呀”。因此, 问起职业,往往只能是回答是搞计算机的。结果可能更尴尬,问的人可能笑嘻嘻地瞅着你,像看怪物一样看着你,接着突然冒出一句灵魂拷问:“我家电脑坏了,你能修不?”不过也不奇怪,那个时候在岛上重装一个 Windows XP 系统都需要100大洋。唉,当初后悔没在中关村的鼎好多学习攒机技术……

image.png

这个印象太深刻,本篇我们就用动画复现一下这种表情,效果如下图所示。

笑脸动画.gif

AnimatedContainer 介绍

在实现之前,先介绍一个新组件 —— AnimatedContainer 。看这个名字就知道和 Container 有关,实际上AnimatedContainer是 Flutter 中的一个动画容器,Container 有的属性基本上它都有,我们看一下二者的构造方法的区别。

AnimatedContainer({
    Key? key,
    this.alignment,
    this.padding,
    Color? color,
    Decoration? decoration,
    this.foregroundDecoration,
    double? width,
    double? height,
    BoxConstraints? constraints,
    this.margin,
    this.transform,
    this.transformAlignment,
    this.child,
    this.clipBehavior = Clip.none,
    Curve curve = Curves.linear,
    required Duration duration,
    VoidCallback? onEnd,
  });

Container({
    Key? key,
    this.alignment,
    this.padding,
    this.color,
    this.decoration,
    this.foregroundDecoration,
    double? width,
    double? height,
    BoxConstraints? constraints,
    this.margin,
    this.transform,
    this.transformAlignment,
    this.child,
    this.clipBehavior = Clip.none,
  });

可以看到,实际上 AnimatedContainer 和 Container 只差了3个属性,而这三个属性就是控制动画的参数:

  • curve:动画曲线,默认是线性;
  • duration:动效时长参数;
  • onEnd:动效结束后的回调方法。

AnimatedContainer的特性是所有涉及外观的属性都会生成一个过渡动效,当这些外观属性发生改变的时候就会使用生成的的动效来完成过渡,从而展现出动画效果。像我们要实现的笑嘻嘻的表情其实就是利用 AnimatedContainer 实现的。

组件结构

我们的笑嘻嘻动效,底部是一个圆形脑袋,上面有两颗眼睛和一个嘴巴,其中眼睛和嘴巴有移动动效,而眼睛的眼珠还有方向的动效。这些动效都可以使用AnimatedContainer来实现。大的页面结构如下:

细节实现

脑袋这个很容易,直接用原型裁剪,设置尺寸和底色即可:

// 脑袋
ClipOval(
  child: Container(
    width: 120,
    height: 120,
    color: Colors.blue,
  ),
),

眼睛左眼和右眼有点不一样,眼球实际就是AnimatedContainer使用 borderRadius 裁剪为圆形,而眼珠是AnimatedContainer的子组件 —— 黑色的圆圈。具体实现向左或向右看使用一个变量 seeLeft 控制,而向左向右的转换过渡效果都由 AnimatedContainer 控制。

  • seeLeft = true,向左看:眼珠对齐的方式是 bottomLeft,左眼纵向方向上稍微往下移一点;右眼往左移动一定的位置,这样就会有向左看的效果了;
  • seeLeft = false,向右看:眼珠对齐的方式是 bottomRight,右眼纵向方向上稍微往下移一点;左眼往右移动一定的位置,这样就会有向右看的效果了;

实现代码如下:

// 左眼
Positioned(
  top: marginTop,
  left: marginLR,
  child: AnimatedContainer(
    alignment:
        seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
    padding: EdgeInsets.all(eyePadding),
    transform: Matrix4.identity()
      ..translate(
          seeLeft ? 0.0 : sideOffset, seeLeft ? eyeOffset : 0.0, 0),
    duration: Duration(seconds: 1),
    curve: Curves.fastOutSlowIn,
    width: eyeSize,
    height: eyeSize,
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(eyeSize / 2),
    ),
    child: ClipOval(
      child: Container(
        color: Colors.black,
        width: eyeBallSize,
        height: eyeBallSize,
      ),
    ),
  ),
),
// 右眼
Positioned(
  top: marginTop,
  right: marginLR,
  child: AnimatedContainer(
    alignment:
        seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
    padding: EdgeInsets.all(eyePadding),
    transform: Matrix4.identity()
      ..translate(seeLeft ? -sideOffset : 0.0,
          seeLeft ? 0.0 : eyeOffset, 0),
    duration: Duration(seconds: 1),
    curve: Curves.fastOutSlowIn,
    width: eyeSize,
    height: eyeSize,
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(eyeSize / 2),
    ),
    child: ClipOval(
      child: Container(
        color: Colors.black,
        width: eyeBallSize,
        height: eyeBallSize,
      ),
    ),
  ),
),

这里的眼珠对齐使用的就是AnimatedContainer 的 alignment参数控制,而眼球的位置使用 Matrix4 的平移实现:

Matrix4.identity()
  ..translate(seeLeft ? -sideOffset : 0.0, seeLeft ? 0.0 : eyeOffset, 0),

笑脸的实现使用ClipPath,绘制两条弧线就可以了,然后平移的幅度和眼珠保持一致,就可以感觉是转头的效果了,AnimatedContainer 部分的代码如下:

// 笑嘻嘻的嘴巴
Positioned(
  bottom: 10,
  height: 40,
  left: 0,
  child: AnimatedContainer(
    alignment:
        seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
    padding: EdgeInsets.all(4.0),
    transform: Matrix4.identity()
      ..translate(seeLeft ? 25.0 : 35.0, 0, 0),
    duration: Duration(seconds: 1),
    curve: Curves.fastOutSlowIn,
    child: ClipPath(
      clipper: SmileClipPath(),
      child: Container(
        width: 60,
        height: 40,
        color: Colors.yellow,
      ),
    ),
  ),
),

笑嘻嘻的嘴巴的裁剪类 SmileClipPath 代码如下:

class SmileClipPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    return Path()
      ..moveTo(0, 0)
      ..arcToPoint(
        Offset(size.width, 0),
        radius: Radius.circular(size.width * 0.55),
        clockwise: false,
      )
      ..arcToPoint(
        Offset(0, 0),
        radius: Radius.circular(size.width),
        clockwise: true,
      );
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

最后,控制状态变量 seeLeft 的变化通过一个按钮点击触发就好了。

floatingActionButton: FloatingActionButton(
  child: Icon(Icons.play_arrow, color: Colors.white),
  onPressed: () {
    setState(() {
      seeLeft = !seeLeft;
    });
  },
),

最终运行效果如下,完整代码已提交至:动画相关代码

笑脸动画.gif

总结

本篇主要介绍 AnimatedContainer 的使用,对于要对 Container 实现动效的场合,可以直接使用AnimatedContainer进行替换,然后通过更改AnimatedContainer的属性就可以实现过渡动效了。比如官网就搞了个随机的形状、弧度和颜色的动效,看着也挺有趣的。

AnimatedContainer 官方动效.gif

以上就是Flutter实现笑嘻嘻的动态表情的示例代码的详细内容,更多关于Flutter动态表情的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android Flutter实现五种酷炫文字动画效果详解

    目录 前言 波浪涌动效果 波浪线跳动文字组 彩虹动效 滚动广告牌效果 打字效果 其他效果 自定义效果 总结 前言 偶然逛国外博客,看到了一个介绍文字动画的库,进入 pub 一看,立马就爱上这个动画库了,几乎你能想到的文字动画效果它都有!现在正式给大家安利一下这个库:animated_text_kit.本篇我们介绍几个酷炫的效果,其他的效果大家可以自行查看官网文档使用. 波浪涌动效果 波浪涌动 上面的动画效果只需要下面几行代码,其中loadUntil用于控制波浪最终停留的高度,取值是0-1.0,如

  • Android Flutter利用贝塞尔曲线画一个小海豚

    目录 前言 效果图 实现步骤 总结 前言 贝塞尔曲线的应用填补了计算机绘制与手绘之前的差距,更能表达人想画出的曲线,为了更好的理解万能的贝塞尔曲线,而海豚是我认为在海洋生物中身体曲线最完美的海洋生物,在海洋中游泳速度最高可达80km/h;比驱逐舰速度还快,学习绘制正好学到了贝塞尔曲线,那么我们今天就用贝塞尔曲线画看看能不能画一只可爱的小海豚呢. 效果图 先上效果图: 实现步骤 path路径绘制贝塞尔曲线的方法非常简单,只需要传入控制点即可,二阶就传1个控制点1个终点,三阶就传2个控制点和1个终点

  • Android Flutter实现图片滑动切换效果

    目录 前言 SlideTransition 介绍 示例效果实现 总结 前言 我们开始来介绍转换类的动画组件,实际上这类转换动画组件也可以自己通过 AnimatedBuilder 或 AnimatedWidget 完成, Flutter 为了简化开发,提供了不少转换动画组件,这类组件通常命名为 xxTransition.本篇要介绍的就是 SlideTransition,顾名思义,就知道是滑动转换动画.我们本篇来实现两张小姐姐图片的滑动切换,效果如下图所示. SlideTransition 介绍 S

  • Flutter实现心动的动画特效

    目录 实现动画 混入 SingleTickerProviderStateMixin 创建动画 抽离成小组件 完整代码 为了追求更好的用户体验,有时候我们需要一个类似心跳一样跳动着的控件来吸引用户的注意力,这是一个小小的优化需求,但是在 Flutter 里动画两件套就像裹脚布一样臭长,所以需要像封装一个 AnimatedWidget,解放生产力. 实现动画 混入 SingleTickerProviderStateMixin 当创建一个 AnimationController 时,需要传递一个vsy

  • 基于Flutter制作一个吃豆人加载动画

    目录 效果图 绘制静态吃豆人.豆豆.眼睛 加入动画属性 总结 效果图 国际惯例,先看效果图: 具体效果就是吃豆人会根据吃不同颜色的豆子改变身体的颜色. 绘制静态吃豆人.豆豆.眼睛 首先,我们需要将这个静态的吃豆人绘制出来,我们可以把吃豆人看做是一个实心圆弧,豆豆和眼睛就是一个圆. 关键代码: //画头 _paint ..color = color.value ..style = PaintingStyle.fill; var rect = Rect.fromCenter( center: Off

  • Flutter实现笑嘻嘻的动态表情的示例代码

    目录 前言 AnimatedContainer 介绍 组件结构 细节实现 总结 前言 身在孤岛有很多无奈,比如说程序员属于比较偏门的职业.尤其是早些年,在行业里跳过几次槽后,可能你就已经认识整个圈子的人了.然后,再跳槽很可能就再次“偶遇”前同事了,用大潘的口头语来说就是:“好尴尬呀”.因此, 问起职业,往往只能是回答是搞计算机的.结果可能更尴尬,问的人可能笑嘻嘻地瞅着你,像看怪物一样看着你,接着突然冒出一句灵魂拷问:“我家电脑坏了,你能修不?”不过也不奇怪,那个时候在岛上重装一个 Windows

  • Flutter 系统是如何实现ExpansionPanelList的示例代码

    在了解ExpansionPanelList实现前,先来了解下MergeableMaterial,它展示多个MergeableMaterialItem组件,当子组件发生变化时,以动画的方式打开或者关闭子组件,MergeableMaterial的父控件需要在主轴方向是一个没有限制的控件,比如SingleChildScrollView.Row.Column等. 基本用法如下: SingleChildScrollView( child: MergeableMaterial( children: [ Ma

  • Flutter实现编写富文本Text的示例代码

    目录 SuperText富文本设计方案 RichText原理 方案设计 解析 代码设计 节点定义 Span构造器定义 SuperText定义 可以修改TextStyle的Span构造器 效果展示 结语 SuperText富文本设计方案 Flutter中要实现富文本,需要使用RichText或者Text.rich方法,通过拆分成List<InlineSpan>来实现,第一感觉上好像还行,但实际使用了才知道,有一个很大的问题就是对于复杂的富文本效果,无法准确拆分出具有实际效果的spans.因此想设

  • 史上最简单的MyBatis动态SQL入门示例代码

    假如有如下的关于书籍基本信息的表: DROP DATABASE IF EXISTS `books`; CREATE DATABASE `books`; USE books; DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(128) DEFAULT NULL, `author` varchar(64) DEFAULT NULL, `pres

  • jQuery 动态粒子效果示例代码

    1.js部分 var RENDERER = { PARTICLE_COUNT : 1000, PARTICLE_RADIUS : 1, MAX_ROTATION_ANGLE : Math.PI / 60, TRANSLATION_COUNT : 500, init : function(strategy){ this.setParameters(strategy); this.createParticles(); this.setupFigure(); this.reconstructMetho

  • Flutter 实现酷炫的3D效果示例代码

    此文讲解3个酷炫的3D动画效果. 下面是要实现的效果: Flutter 中3D效果是通过 Transform 组件实现的,没有变换效果的实现: class TransformDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('3D 变换Demo'), ), body: Container( alignm

  • Django与AJAX实现网页动态数据显示的示例代码

    前言 这部分已经折腾我两天了,还是没有头绪,可能还会折腾更久,最后在第三天上午解决问题,在一个不起眼的地方被坑了,jQuery加载的问题.会者不难,难者不会,希望后面人少走弯路吧 环境 windows10 pycharm2017.3.3 professional edition python3.6.4 django2.0.2 方法 创建后台读取数据函数,用于后台从数据库读取数据.在views.py文件内增加以下代码 from django.http import JsonResponse def

  • Flutter仿钉钉考勤日历的示例代码

    本文主要介绍了Flutter仿钉钉考勤日历的示例代码,分享给大家,具体如下: 效果 原型 开发 1. 使用 // 考勤日历 DatePickerDialog( initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2030), onDateChanged: onDateChanged, // 0:无状态,1:正常考勤 2:异常考情,迟到,早退, // 若不满一个月,日历会自动用0补满一个月 check

  • Element实现动态表格的示例代码

    目录 [代码背景] [代码实现] #1# -> 代码复用的基础是你需要一个可复用的组件 #2# -> 在展示页面使用动态表格组件 #3# -> 如何给动态表格根据需求动态添加序号列/索引列 [代码背景] 有这样一个业务需求场景,有大概十几张表归属于某个类别,用户希望在同一个页面,通过选择不同的查询指标展示不同的表格,这些表的表头样式类似但是又不完全相同,怎么做呢? 到目前为止所有基于Element UI的表格样式都是直接在页面写死的,像官方这样: <el-table :data=&

  • python通过pillow识别动态验证码的示例代码

    目录 环境配置  安装 pillow(PIL)库 识别过程 生活中,我们在登录微博,邮箱的时候,常常会碰到验证码.在工作时,如果想要爬取一些数据,也会碰到验证码的阻碍.本次试验将带领大家认识验证码的一些特性,并利用 Python 中的 pillow 库完成对验证码的破解. 环境配置 Python 2.7 Pillow 模块 有个问题就是python2.7目前只能让使用到2020年,现在再利用2.7下载好多东西都会报错,也该是时候更新到python3.7了,本文还是依赖于2.7的环境. 识别验证码

随机推荐