基于Flutter制作一个心碎动画特效

作者:老李code 时间:2023-05-27 06:07:47 

前言

继续动画探索,今天用Flutter制作一个心碎的感觉,灵感来源于今天的股市,哎,心哇凉哇凉的。废话不多说,开始。

效果图先上:

基于Flutter制作一个心碎动画特效

实现步骤

1、绘制一个心

首先我们使用两段三阶贝塞尔曲线制作一个心型,这里因为需要实现心碎的效果,所以我们需要将心的两段用两段路径path进行绘制出来,效果:

基于Flutter制作一个心碎动画特效

绘制代码:

canvas.translate(size.width / 2, size.height / 2);
Paint paint = Paint();
paint
 ..style = PaintingStyle.stroke
 ..strokeWidth = 2
 ..color = Colors.black87;
Path path = Path();
path.moveTo(0, 0);
path.cubicTo(-200, -80, -60, -240, 0, -140);
path.close();
Path path2 = Path();
canvas.save();
canvas.drawPath(
   path,
   paint
   ..color = Colors.red
     ..style = PaintingStyle.stroke);
canvas.restore();
path2.cubicTo(200, -80, 60, -240, 0, -140);
path2.close();
canvas.drawPath(
   path2,
   paint..color = Colors.black87);

2、绘制心的裂痕

我们看到心确实分成两半了,但是中间还缺少裂痕,接下来我们就绘制心碎的裂痕,也很简单,在两段路径path闭合前进行绘制线,效果:

基于Flutter制作一个心碎动画特效

绘制代码:

path.relativeLineTo(-10, 30);
path.relativeLineTo(20, 5);
path.relativeLineTo(-20, 30);
path.relativeLineTo(20, 20);
path.relativeLineTo(-10, 20);
path.relativeLineTo(10, 10);

path2.relativeLineTo(-10, 30);
path2.relativeLineTo(20, 5);
path2.relativeLineTo(-20, 30);
path2.relativeLineTo(20, 20);
path2.relativeLineTo(-10, 20);
path2.relativeLineTo(10, 10);

OK,我们已经看到心已经有了裂痕,如何心碎,只需将画布进行翻转一定角度即可,这里我们将画布翻转45°,看下效果:

左边:

基于Flutter制作一个心碎动画特效

右边:

基于Flutter制作一个心碎动画特效

3、加入动画

已经有心碎的感觉了,接下来加入动画元素让心碎的过程动起来。

思路: 我们可以想一下,心碎的过程是什么样子,心的颜色慢慢变灰,心然后慢慢裂开,下方的动画运动曲线看起来更符合心碎的过程,里面有不舍,不甘,但最后心还是慢慢的碎了。

基于Flutter制作一个心碎动画特效

我们把画笔进行填充将这个动画加入进来看下最终效果。

基于Flutter制作一个心碎动画特效

是不是心碎了一地。

知识点: 这里我们需要找到红色和灰色的RGB色值,通过Color.fromRGBO(r, g, b, opacity)方法赋值颜色的色值。然后通过动画值改变RGB的值即可。 这里我使用的色值是:

红色:Color.fromRGBO(255, 0, 0, 1)灰色:Color.fromRGBO(169, 169, 169, 1)

完整代码

class XinSui extends StatefulWidget {
 const XinSui({Key? key}) : super(key: key);

@override
 _XinSuiState createState() => _XinSuiState();
}

class _XinSuiState extends State<XinSui> with SingleTickerProviderStateMixin {
 late AnimationController _controller =
     AnimationController(vsync: this, duration: Duration(milliseconds: 4000))
       ..repeat();
 late CurvedAnimation cure =
     CurvedAnimation(parent: _controller, curve: Curves.bounceInOut);

late Animation<double> animation =
     Tween<double>(begin: 0.0, end: 1.0).animate(cure);

@override
 Widget build(BuildContext context) {
   return Container(
     child: CustomPaint(
       size: Size(double.infinity, double.infinity),
       painter: _XinSuiPainter(animation),
     ),
   );
 }

@override
 void dispose() {
   _controller.dispose();
   super.dispose();
 }
}

class _XinSuiPainter extends CustomPainter {
 Animation<double> animation;

_XinSuiPainter(this.animation) : super(repaint: animation);

@override
 void paint(Canvas canvas, Size size) {
   canvas.translate(size.width / 2, size.height / 2);
   Paint paint = Paint();
   paint
     ..style = PaintingStyle.stroke
     ..strokeWidth = 2
     ..color = Colors.black87;
   Path path = Path();
   path.moveTo(0, 0);
   path.cubicTo(-200, -80, -60, -240, 0, -140);
   path.relativeLineTo(-10, 30);
   path.relativeLineTo(20, 5);
   path.relativeLineTo(-20, 30);
   path.relativeLineTo(20, 20);
   path.relativeLineTo(-10, 20);
   path.relativeLineTo(10, 10);
   path.close();
   Path path2 = Path();
   canvas.save();
   canvas.rotate(-pi / 4 * animation.value);
   canvas.drawPath(
       path,
       paint
       ..color = Colors.red
         ..color = Color.fromRGBO(
             255 - (86 * animation.value).toInt(),
             (animation.value * 169).toInt(),
             (animation.value * 169).toInt(),
             1)

..style = PaintingStyle.fill);
   canvas.restore();
   path2.cubicTo(200, -80, 60, -240, 0, -140);
   path2.relativeLineTo(-10, 30);
   path2.relativeLineTo(20, 5);
   path2.relativeLineTo(-20, 30);
   path2.relativeLineTo(20, 20);
   path2.relativeLineTo(-10, 20);
   path2.relativeLineTo(10, 10);
   path2.close();
   canvas.rotate(pi / 4 * animation.value);
   canvas.drawPath(
       path2,paint);
 }
 @override
 bool shouldRepaint(covariant _XinSuiPainter oldDelegate) {
   return oldDelegate.animation != animation;
 }
}

小结

动画曲线Curves配合绘制可以实现很多好玩的东西,这个需要勤加练习方能掌握,仅将此心碎献给今天受伤的股民朋友们

来源:https://juejin.cn/post/7090457954415017991

标签:Flutter,心碎,动画
0
投稿

猜你喜欢

  • C#实现缩放和剪裁图片的方法示例

    2023-06-03 11:09:31
  • Android 客户端RSA加密的实现方法

    2023-05-23 13:50:43
  • Android编程四大组件之BroadcastReceiver(广播接收者)用法实例

    2023-07-23 16:45:39
  • c#实现隐藏与显示任务栏的方法详解

    2023-05-27 11:59:04
  • java 命名空间 命名规则第1/2页

    2021-06-06 14:20:19
  • SpringAOP切点函数实现原理详解

    2021-09-05 11:00:59
  • springboot-curd基于mybatis项目搭建

    2023-12-08 10:41:05
  • 分析ABA问题的本质及其解决办法

    2021-12-20 13:59:26
  • Mybatis + js 实现下拉列表二级联动效果

    2022-09-14 03:43:06
  • 解决android关于打开虚拟机时右侧工具栏不显示的问题

    2023-02-24 12:42:54
  • MyBatis-Plus 自定义sql语句的实现

    2022-12-24 23:16:16
  • Spring的事务机制实例代码

    2021-09-11 07:46:23
  • IDEA插件之Mybatis Log plugin 破解及安装方法

    2023-09-24 22:30:16
  • Android开发中的几种网络请求方式详解

    2021-06-01 17:45:21
  • c语言动态数组示例

    2023-11-02 22:56:44
  • C#中的try catch finally用法分析

    2021-06-20 18:31:28
  • Java分析讲解序列化与字典功能的序列化

    2021-11-12 11:19:25
  • Java4Android开发教程(一)JDK安装与配置

    2022-02-04 22:33:12
  • WPF+SkiaSharp实现自绘投篮小游戏

    2023-09-06 22:59:51
  • Android 触摸事件监听(Activity层,ViewGroup层,View层)详细介绍

    2023-02-07 00:58:51
  • asp之家 软件编程 m.aspxhome.com