Flutter——Canvas之最权威仪表盘进度实战

387 阅读2分钟

开发背景:

公司需求; 在这里插入图片描述

  1. 确定圆心坐标
   double radius = size.width / 2;
   double centerX = size.width / 2;
   double centerY = size.height;
  1. 绘制最下面的半圆
Paint backgroundPaint = Paint()
      ..color = Color(0xffF8F8F8)
      ..style = PaintingStyle.fill;

    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: radius),
      pi,
      pi,
      true,
      backgroundPaint,
    );

  1. 绘制中间的半圆
    backgroundPaint.color = Color(0xff28AFF3);
    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: radius - 11.w),
      pi, // Start angle
      pi, // Sweep angle
      true, // Use center
      backgroundPaint,
    );

  1. 加粗样式
///每一份的角度值
    double lineJiaodu = 0;
    ///当前进度占比值
    double shanxingbaifenbi = 0;
    if (maxNumber != 0) {
    ///传进来的进度值,加50个值,后面避免每次绘制占比都是满状态
      var totalNumber = maxNumber + 50;
      lineJiaodu = pi / totalNumber;
      shanxingbaifenbi = maxNumber / totalNumber;
    }
    ///角度
    double angle = pi + lineJiaodu * maxNumber;
    ///计算开始位置的坐标
    double startX = centerX + (radius - 25.w) * cos(angle);
    double startY = centerY + (radius - 25.w) * sin(angle);
    double endX = startX - 70.w * cos(angle); // 刻度线长度为10
    double endY = startY - 70.w * sin(angle);
    ///避免指针绘制属于叠加状态
    if (maxNumber == 1 || maxNumber == 0) {
      startY = startY - 3.w;
      endY = endY - 3.w;
    }
  1. 绘制进度颜色

    backgroundPaint.color = Color(0xffF6A658);
    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: radius - 11.w),
      pi, // Start angle
      shanxingbaifenbi * pi, // Sweep angle
      true, // Use center
      backgroundPaint,
    );
  1. 绘制半圆
   backgroundPaint.color = Color(0xffF8F8F8);
    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: radius - 40.w),
      pi,
      pi,
      true,
      backgroundPaint,
    );

    // backgroundPaint.color = Colors.red;
    backgroundPaint.color = Color(0xffF5F5F5);
    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: centerX * 0.62),
      pi,
      pi,
      true,
      backgroundPaint,
    );

    backgroundPaint.color = Color(0xffFFFFFF);
    canvas.drawArc(
      Rect.fromCircle(center: Offset(centerX, centerY), radius: centerX * 0.4),
      pi, // Start angle
      pi, // Sweep angle
      true, // Use center
      backgroundPaint,
    );
  1. 绘制圆上的刻度线
 Paint linePaint = Paint()
      ..color = Colors.white
      ..strokeWidth = 2.w;

    double angleIncrement = pi / 7; // 每个刻度之间的角度增量

    for (int i = 0; i <= 7; i++) {
      double angle = pi + angleIncrement * i;
      if (i == 0) {
        angle = angle + 0.02222222;
      }
      if (i == 7) {
        angle = angle - 0.02222222;
      }
      double startX = centerX + (radius - 21.w) * cos(angle);
      double startY = centerY + (radius - 21.w) * sin(angle);
      double endX = startX + 10.w * cos(angle); // 刻度线长度为10
      double endY = startY + 10.w * sin(angle);
      canvas.drawLine(Offset(startX, startY), Offset(endX, endY), linePaint);
    }
  1. 绘制指针线
    Paint linePaint1 = Paint()
      ..color = Colors.white
      ..strokeWidth = 6.w;

    canvas.drawLine(Offset(startX, startY), Offset(endX, endY), linePaint1);

  1. 绘制底部文本最大值

    drawText(
      "$maxNumber",
      size.width / 2,
      size.height,
      "s",
      24.sp,
      Color(0xff333333),
      "center",
      "bottom",
    );