这个组件参考了很多大佬的代码和思路,感谢他们的无私分享
先来一些示意图吧:
介绍
这是一个能够将一个或多个Path
动画化展示的组件。接下来看看入参吧:
final List<Path> Function(Size size) paths;
final Widget? header;
final Color color;
final double strokeWidth;
final StrokeCap strokeCap;
final StrokeJoin strokeJoin;
final Animation<double> animation;
final int? fps;
final EdgeInsetsGeometry padding;
其中,paths
,color
,animation
必传。
paths
paths
是一个需要返回List<Path>
的函数,size
为AnimatedPath
的大小,由LayoutBuilder
获取,目的是为了方便使用者根据Size
的不同来创建响应式的Path
。
比如你想创建一条在正方形内从左上到右下的路径,在10x10的正方形里就是:
Path path = Path();
path.moveTo(0, 0);
path.moveTo(10, 10);
如果是100x100的正方形那就是
Path path = Path();
path.moveTo(0, 0);
path.moveTo(100, 100);
这种情况下这个Size就很有用了。当然,不使用Size也是可以的。
animation
AnimatedPath
是一个专注于解析Path
的库,不会自己创建AnimatedController
然后暴露播放和暂停的函数,而是需要使用者自己创建AnimatedController
并将其传入组件中。你也可以使用CurvedAnimation
等来对AnimatedController
进行装饰。以下是一个示例:
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
final CurvedAnimation curve = CurvedAnimation(
curve: Curves.easeInOut,
parent: controller,
);
final Tween<double> tween = Tween(begin: 0, end: 1);
// 使用时:
AnimatedPath(
paths: (size) => createPath(size),
animation: tween.animate(curve),
)
UI相关
color
:必传,线条的颜色strokWidth
:选传,线条的粗细,默认为1strokCap
:选传,线条的结束的样式,默认为StrokCap.square
strokJoin
:选传,线条连接的样式,默认为StrokJoin.miter
其中StorkCap和StrokJoin最好去参阅一下源码,官方写得更清楚且有一些样例可供参考。
原理
这个库的原理很简单,就是将传入的Path
根据Animation
的值来创建一个新的Path
。Path
中有一个extractPath
函数,传入start
和end
,返回该Path
的对应片段。那么这里只需要start
传0,end
传入进度即可。参考了张风捷特烈大佬的绘制番外中的代码,十分感谢。
扩展功能
扩展功能之fps
在写上面那个利萨茹曲线的示例时,发现一旦将那几个参数设置地大一点,到了动画的后期总是会出现卡顿。于是参考豆豆大佬的flutter_tilt库也实现了一个fps限制器。一般来说无需传入,除非实在很卡那就看情况传个60或者144吧。
扩展功能之头部特效
在做第三个示例时突发奇想想在动画上添加一个火花特效来跟随进度条。于是就加上了header
和padding
两个参数。其中header
传入一个任意Widget,它将跟随动画的进度而移动。padding
则是用于处理一些可能导致header
显示不完全的特殊情况。
要实现这个需求要做两件事:1是获取动画进度当前的位置,2是将它展示出来。
在Path的那堆方法里找到一个叫getTangentForOffset
的函数,它用于计算当前Path上某个点在当前画面中的位置。那么我只需把前面算出来的新Path的总长度放进去就能完成第一点。
至于第二点的展示我最开始想的是如何将Widget在Painter
中画出来。想了很久都没能成功,最后决定还是使用Stack
。大致方案是在Stack
中以Painter
为底然后加上一个或多个Position
。因此需要计算出Position
的位置。但是如果为直接使用第一点返回的坐标,那header
实际上会有偏移。
左图为直接使用坐标,右图为计算后得出的正确坐标
为了消除偏移,在计算坐标时需要减去header
本身的大小,那么该如何获取header
的大小呢?我这里选择的是杜文老师的AfterLayout。
最后
这个库已经开源并上传到pub.dev,有兴趣的可以试着用一下,能顺手点个赞给个like就更好了,谢谢~
写完了才发现pub上已经有叫animated_path的同名库,只能改成animated_path_builder了..
pub: pub.dev/packages/an…
GitHub: github.com/Dabbit-Chan…