Flutter

flutter-心形轨迹动画

2021-03-31  本文已影响0人  浮华_du

右边半个心❤边缘轨迹

class PainterDotWidget extends StatefulWidget {
  final double width;
  final double height;
  PainterDotWidget({@required this.width, @required this.height, Key key})
      : super(key: key);

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

class _PainterDotWidgetState extends State<PainterDotWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _controller; // 动画 controller
  Animation<double> _animation; // 动画
  double left; // 小圆点的left(动态计算)
  double top; // 小远点的right(动态计算)

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
        duration: Duration(milliseconds: 2000), vsync: this);
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
      ..addListener(() {
        if (_animation.status == AnimationStatus.completed) {}
      });

    // 三阶贝塞尔曲线用值
    ///p0 = width / 2, height / 4
    ///p1 = (width * 6) / 7, height / 9)
    ///p2 = (width * 13) / 13, (height * 2) / 5)
    ///p3 = width / 2, (height * 7) / 12
    var x0 = widget.width / 2;
    var y0 = widget.height / 4;

    var x1 = (widget.width * 6) / 7;
    var y1 = widget.height / 9;

    var x2 = (widget.width * 13) / 13;
    var y2 = (widget.height * 2) / 5;

    var x3 = widget.width / 2;
    var y3 = widget.height * 7 / 12;

    _animation.addListener(() {
      // t 动态变化的值
      var t = _animation.value;
      if (mounted)
        setState(() {
// B3(t) = (1-t)^3*P0+3t(1-t)^2*P1+3t^2(1-t)*P2+t^3*P3,  t属于 [0,1]
          left = pow(1 - t, 3) * x0 +
              3 * t * pow(1 - t, 2) * x1 +
              3 * pow(t, 2) * (1 - t) * x2 +
              pow(t, 3) * x3;

          top = pow(1 - t, 3) * y0 +
              3 * t * pow(1 - t, 2) * y1 +
              3 * pow(t, 2) * (1 - t) * y2 +
              pow(t, 3) * y3;
        });
    });

    // 初始化小圆点的位置
    left = x0;
    top = y0;

    // 显示小圆点的时候动画就开始
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          left: left - 7,
          top: top - 7,
          child: ClipOval(
            child: Container(
              width: 14,
              height: 14,
              color: Colors.blue,
            ),
          ),
        ),
      ],
    );
  }
}

上一篇 下一篇

猜你喜欢

热点阅读