Flutter利用Hero组件实现自定义路径效果的动画

作者:岛上码农 时间:2023-06-25 13:46:29 

前言

我们在 页面切换转场动画,英雄救场更有趣!介绍了 Hero 动画效果,使用 Hero 用于转场能够提供非常不错的体验。既然称之为英雄,肯定还有其他技能,本篇我们就来探索一下 Hero 动画的返回效果。

Hero 的定义

Hero 组件是一个 StatefulWidget,构造方法如下:

const Hero({
  Key? key,
  required this.tag,
  this.createRectTween,
  this.flightShuttleBuilder,
  this.placeholderBuilder,
  this.transitionOnUserGestures = false,
  required this.child,
})

其中 createRectTween 就是一个矩形插值,用于控制 Hero 组件的路径。实际上,和普通动画一样,也是有一个时间曲线,取值范围是0-1.0,然后createRectTween保证 Hero 组件动画前后能够达到矩形指定位置和大小。下面一张图是官网的说明图:

Flutter利用Hero组件实现自定义路径效果的动画

image.png

RectTween

RectTween 和 Tween类似,实际上就是矩阵在动画过程中的变化。我们来看 RectTween 的定义:

class RectTween extends Tween<Rect?> {
  RectTween({ Rect? begin, Rect? end }) : super(begin: begin, end: end);

  /// 通过给定的动画时间值构建新的插值矩形
  @override
  Rect? lerp(double t) => Rect.lerp(begin, end, t);
}

这个类很简单,其实就是每次动画时间点上调用 Rect.lerp 构建一个插值的矩形。Rect.lerp 方法如下:

static Rect? lerp(Rect? a, Rect? b, double t) {
    assert(t != null);
    if (b == null) {
      if (a == null) {
        return null;
      } else {
        final double k = 1.0 - t;
        return Rect.fromLTRB(a.left * k, a.top * k, a.right * k, a.bottom * k);
      }
    } else {
      if (a == null) {
        return Rect.fromLTRB(b.left * t, b.top * t, b.right * t, b.bottom * t);
      } else {
        return Rect.fromLTRB(
          _lerpDouble(a.left, b.left, t),
          _lerpDouble(a.top, b.top, t),
          _lerpDouble(a.right, b.right, t),
          _lerpDouble(a.bottom, b.bottom, t),
        );
      }
    }
  }

在矩形 a 和矩形 b 都不为空的时候,返回的就是一个通过定点定义的新的矩形。这里的关键是_lerpDouble 方法,其实最终就是根据动画时间完成顶点的移动。

double? lerpDouble(num? a, num? b, double t) {
  /// ...
  return a * (1.0 - t) + b * t;
}

也就是从矩形 a  的顶点逐步移动到矩形 b的顶点,从而完成了两个矩形的动画过渡。有了这个基础我们就可以构建自定义的 RectTween 了。和我们的之前说过的动画曲线(动画曲线天天用,你能自己整一个吗?看完这篇你就会了!)是类似的。

自定义RectTween

我们来一个自定义 RectTween,然后保证起始点是矩形 a,结束点是矩形 b,然后中间沿曲线变动就可以了。下面是我们利用曲线将时间转换后得到的一个自定义 RectTween。其中使用曲线转换后的transformT取值还是从0-1.0,然后使用_rectMove 方法就能实现从开始的矩形过渡到结束的矩形了。

class CustomRectTween extends RectTween {
  final Rect begin;
  final Rect end;

  CustomRectTween({required this.begin, required this.end})
      : super(begin: begin, end: end);

  @override
  Rect lerp(double t) {
    double transformT = Curves.easeInOutBack.transform(t);

    var rect = Rect.fromLTRB(
        _rectMove(begin.left, end.left, transformT),
        _rectMove(begin.top, end.top, transformT),
        _rectMove(end.right, end.right, transformT),
        _rectMove(begin.bottom, end.bottom, transformT));

    return rect;
  }

  double _rectMove(double begin, double end, double t) {
    return begin * (1 - t) + end * t;
  }
}

运行效果

可以看到结束的时候,有个回弹效果,那是因为使用了Curves.easeInOutBack 这个曲线。源码已上传至:动画相关源码。

Flutter利用Hero组件实现自定义路径效果的动画

运行效果

来源:https://mp.weixin.qq.com/s/irXxttIRDFyGkPJyUTnp8w

标签:Flutter,Hero组件,路径动画
0
投稿

猜你喜欢

  • Gradle进阶使用结合Sonarqube进行代码审查的方法

    2021-12-17 08:49:56
  • Android解决ScrollView下嵌套ListView和GridView中内容显示不全的问题

    2023-09-26 23:32:58
  • QT自定义QTextEdit实现大数据的实时刷新显示功能实例

    2023-05-06 03:18:28
  • 在Eclipse安装Spring boot插件的步骤(图文)

    2023-01-14 05:04:05
  • Java 网络编程socket编程等详解

    2023-09-09 16:43:12
  • 关于Java反编译字节码文件

    2021-10-07 01:41:32
  • java对list<Object>进行手动分页实现

    2023-01-13 13:41:01
  • logback输出日志屏蔽quartz的debug等级日志方式

    2023-08-04 23:40:04
  • C++作用域与函数重载的实现

    2022-04-30 06:28:30
  • @ConfigurationProperties加载外部配置方式

    2023-11-09 01:14:32
  • C++临时性对象的生命周期详细解析

    2023-01-22 04:26:01
  • C#如何调用MFC 窗口 DLL

    2022-04-14 09:57:51
  • Android5.0中多种水波纹效果的实现代码

    2023-09-23 04:42:53
  • Java负载均衡算法实现之轮询和加权轮询

    2023-07-16 15:27:17
  • 跨域解决方案Jsonp原理解析

    2023-11-07 18:48:05
  • MapStruct处理Java中实体与模型间不匹配属性转换的方法

    2023-08-02 22:31:28
  • SpringBoot 静态资源导入及首页设置问题

    2023-11-26 22:45:07
  • Android 吸入动画效果实现分解

    2021-10-24 16:55:28
  • java对象和json的来回转换知识点总结

    2023-08-01 23:35:57
  • Java实现上传文件图片到指定服务器目录

    2023-06-28 00:23:32
  • asp之家 软件编程 m.aspxhome.com