Flutter canvas 画一条会动的波浪线 进度条

之前用 Flutter Canvas 画过一个三角三角形,html 的 Canvas 也画过一次类似的, 今天用 Flutter Canvas 试了下 感觉差不多:

html 版本

大致效果如下:

思路和 html 实现的类似:

也就是找出点的位置,使用二阶贝塞尔曲线实现:

Flutter canvas 画一条会动的波浪线 进度条_第1张图片

 代码如下:
import 'package:flutter/material.dart';

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

  @override
  State createState() => _PageCanvasState();
}

class _PageCanvasState extends State with TickerProviderStateMixin {
  late Animation animation;
  late AnimationController controller;
  double _waveHeight = 0.5;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
    animation = Tween(begin: 0, end: 1).animate(controller);
    controller.repeat();
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Canvas'),
        backgroundColor: Colors.blue,
      ),
      body: Column(
        children: [
          AnimatedBuilder(
              animation: controller,
              builder: (context, widget) {
                return CustomPaint(
                  size: Size(size.width, size.height / 3),
                  painter: MyPainter(animation.value, _waveHeight),
                );
              }),
          const SizedBox(
            height: 60,
          ),
          Center(
            child: SizedBox(
              // color: Colors.grey,
              width: 200,
              height: 200,
              child: ClipOval(
                child: Container(
                  color: Colors.grey.withOpacity(0.3),
                  child: AnimatedBuilder(
                      animation: controller,
                      builder: (context, widget) {
                        return CustomPaint(
                          size: Size(size.width, size.height / 3),
                          painter: MyPainter2(animation.value, _waveHeight),
                        );
                      }),
                ),
              ),
            ),
          ),
          const SizedBox(
            height: 20,
          ),
          Slider(
            min: 0,
            max: 2,
            value: _waveHeight,
            onChanged: (value) {
              setState(() {
                _waveHeight = value;
              });
              //_waveHeight = value;
            },
          )
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    // TODO: implement dispose
    super.dispose();
  }
}

class MyPainter extends CustomPainter {
  final double value;
  final double waveHeight;
  const MyPainter(this.value, this.waveHeight);
  @override
  void paint(Canvas canvas, Size size) {
    // print(value);

    Paint paint = Paint();
    Path path = Path();

    double positionX = -size.width * value;
    double positionY = 100;
    double positionRange = 5 * (1 + waveHeight);

    double positionX2 = -size.width * (1 - value);
    double positionY2 = 110;
    double positionRange2 = 10 * (1 + waveHeight);

    double positionX3 = -size.width * (1.3 - value);
    double positionY3 = 120;
    double positionRange3 = 20 * (1 + waveHeight);

    double step = size.width / 4;
    //
    path.moveTo(0 + positionX, positionY);
    for (int i = 1; i < 13; i++) {
      if (i % 2 == 1) {
        path.quadraticBezierTo(step * (2 * i - 1) + positionX,
            positionY - positionRange, step * (2 * i) + positionX, positionY);
      } else {
        path.quadraticBezierTo(step * (2 * i - 1) + positionX,
            positionY + positionRange, step * (2 * i) + positionX, positionY);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue.withOpacity(0.2);
    canvas.drawPath(path, paint);

    canvas.save();
    canvas.restore();

    path = Path();
    path.moveTo(0 + positionX2, positionY2);

    for (int i = 1; i < 13; i++) {
      if (i % 2 == 1) {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX2,
            positionY2 - positionRange2,
            step * (2 * i) + positionX2,
            positionY2);
      } else {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX2,
            positionY2 + positionRange2,
            step * (2 * i) + positionX2,
            positionY2);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue.withOpacity(0.6);
    canvas.drawPath(path, paint);

    canvas.save();
    canvas.restore();

    path = Path();
    path.moveTo(0 + positionX3, positionY3);

    for (int i = 1; i < 13; i++) {
      if (i % 2 == 1) {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX3,
            positionY3 - positionRange3,
            step * (2 * i) + positionX3,
            positionY3);
      } else {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX3,
            positionY3 + positionRange3,
            step * (2 * i) + positionX3,
            positionY3);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue;
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return oldDelegate != this;
    //return true;
  }
}

class MyPainter2 extends CustomPainter {
  final double value;
  final double waveHeight;
  const MyPainter2(this.value, this.waveHeight);
  @override
  void paint(Canvas canvas, Size size) {
    // print(value);

    Paint paint = Paint();
    Path path = Path();

    double positionX = -size.width * value;
    double positionY = 50;
    double positionRange = 5 * (1 + waveHeight);

    double positionX2 = -size.width * (1 - value);
    double positionY2 = 60;
    double positionRange2 = 10 * (1 + waveHeight);

    double positionX3 = -size.width * (1.3 - value);
    double positionY3 = 70;
    double positionRange3 = 20 * (1 + waveHeight);

    double step = size.width / 4;
    //
    path.moveTo(0 + positionX, positionY);

    for (int i = 1; i < 13; i++) {
      if (i % 2 == 0) {
        path.quadraticBezierTo(step * (2 * i - 1) + positionX,
            positionY - positionRange, step * (2 * i) + positionX, positionY);
      } else {
        path.quadraticBezierTo(step * (2 * i - 1) + positionX,
            positionY + positionRange, step * (2 * i) + positionX, positionY);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue.withOpacity(0.2);
    canvas.drawPath(path, paint);

    canvas.save();
    canvas.restore();

    path = Path();
    path.moveTo(0 + positionX2, positionY2);

    for (int i = 1; i < 13; i++) {
      if (i % 2 == 0) {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX2,
            positionY2 - positionRange2,
            step * (2 * i) + positionX2,
            positionY2);
      } else {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX2,
            positionY2 + positionRange2,
            step * (2 * i) + positionX2,
            positionY2);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue.withOpacity(0.6);
    canvas.drawPath(path, paint);

    canvas.save();
    canvas.restore();

    path = Path();
    path.moveTo(0 + positionX3, positionY3);

    for (int i = 1; i < 13; i++) {
      if (i % 2 == 0) {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX3,
            positionY3 - positionRange3,
            step * (2 * i) + positionX3,
            positionY3);
      } else {
        path.quadraticBezierTo(
            step * (2 * i - 1) + positionX3,
            positionY3 + positionRange3,
            step * (2 * i) + positionX3,
            positionY3);
      }
    }

    path.lineTo(step * 10, 250);
    path.lineTo(0, 250);
    path.close();
    paint.color = Colors.blue;
    canvas.drawPath(path, paint);

    canvas.save();
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return oldDelegate != this;
    //return true;
  }
}

你可能感兴趣的:(Flutter,前端,Flutter,Canvas,flutter)