Flutter -自定义进度条

k2arahey  于 2023-05-30  发布在  Flutter
关注(0)|答案(1)|浏览(277)

我真的被这样的曲线进度条卡住了,它有溢出进度的自定义颜色(这些三角形)。有什么想法如何实现它?

这就是我目前所拥有的-只是一个有价值的弯曲进度条,但我不知道如何使用这些渐变三角形:

class ConvexProgressPainter extends CustomPainter {
  int progress;
  ConvexProgressPainter({required this.progress});

  @override
  void paint(Canvas canvas, Size size) {
    final quadraticCurve = QuadraticBezier([
      vmath.Vector2(0, size.height),
      vmath.Vector2(size.width / 2, 0),
      vmath.Vector2(size.width, size.height),
    ]);

    // Render main background points
    final fullControlPoints = List.generate(size.width.toInt(), (index) {
      final point = quadraticCurve.pointAt(index.toDouble() / size.width);
      return Offset(
        point.x,
        point.y,
      );
    }).toList();

    final mainSpline = CatmullRomSpline(fullControlPoints);
    final mainBezierPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 20
      ..shader = LinearGradient(colors: [
        HexColor.fromHex('FFC738'),
        HexColor.fromHex('FF1886'),
      ]).createShader(Offset(0, size.height) & size);

    canvas.drawPoints(
      PointMode.points,
      mainSpline.generateSamples().map((e) => e.value).toList(),
      mainBezierPaint,
    );

    // Render progress points
    final progressValue = progress * (size.width / 120);

    final progressControlPoints = List.generate(progressValue.toInt(), (index) {
      final point = quadraticCurve.pointAt(index.toDouble() / size.width);
      return Offset(
        point.x,
        point.y,
      );
    }).toList();

    var progressTextAngle = 3;
    final progressSpline = CatmullRomSpline(progressControlPoints);
    final progressBezierPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 20
      ..shader = LinearGradient(colors: [
        HexColor.fromHex('0063FF'),
        HexColor.fromHex('6000FF'),
      ]).createShader(Offset(0, size.height) & size);

    canvas.drawPoints(
      PointMode.points,
      progressSpline.generateSamples().map((e) => e.value).toList(),
      progressBezierPaint,
    );

    // rotate the canvas
    canvas.save();

    final radians = progressTextAngle * pi / 180;
    canvas.rotate(radians);

    TextSpan span = TextSpan(
        style: AppTheme.caption.copyWith(color: Colors.white, fontSize: 10),
        text: '$progress%');
    TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
    tp.layout();
    final x = progressControlPoints.last.dx;
    final y = progressControlPoints.last.dy - tp.size.height / 2 - 2;
    rotate(canvas, x, y, radians, tp);
    //tp.paint(canvas, Offset(x, y));

    canvas.restore();
  }

  void rotate(
      Canvas canvas, double cx, double cy, double angle, TextPainter tp) {
    // Calculate delta offset with reference to which any text should
    // paint, such that the centre of the text will be
    // at the given textCentrePoint
    final delta = Offset(cx - tp.size.width, cy - tp.size.height);

    canvas.save();
    canvas.translate(cx, cy);
    canvas.rotate(angle);
    canvas.translate(-cx, -cy);
    tp.paint(canvas, delta);
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

现在看起来是这样的

idfiyjo8

idfiyjo81#

我会让你的画布作为堆栈的顶部元素,同时让红色/粉色部分透明。堆叠的下层可以是稍微旋转的容器,其包含梯度。轻微的旋转是这样做的。

new RotationTransition(
  turns: new AlwaysStoppedAnimation(45 / 360),
  child: Container(),
)

相关问题