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

前言 继续动画探索,今天用Flutter制作一个心碎的感觉,灵感来源于今天的股市,哎,心哇凉哇凉的。废话不多说,开始。 效果图先上:实现步骤 1、绘制一个心 首

前言

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

效果图先上:

实现步骤

1、绘制一个心

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

绘制代码:

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闭合前进行绘制线,效果:

绘制代码:

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°,看下效果:

左边:

右边:

3、加入动画

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

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

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

是不是心碎了一地。

知识点: 这里我们需要找到红色和灰色的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配合绘制可以实现很多好玩的东西,这个需要勤加练习方能掌握,仅将此心碎献给今天受伤的股民朋友们

到此这篇关于基于Flutter制作一个心碎动画特效的文章就介绍到这了,更多相关Flutter心碎动画内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!

您可能有感兴趣的文章
图文详解Flutter单例的如何实现

Flutter中如何使用setState时的6个简单技巧总结

Flutter路由fluro引入配置和如何使用的具体方法

Flutter如何实现下拉刷新和上拉加载更多

封装flutter状态管理工具示例详解