0

弧线是使用 CustomPainter 小部件绘制的。绘制的小部件用于显示信用评分。随着指标的移动,每个弧线都应该被填充。我已经为这些提出了所有逻辑,但我无法按顺序填写弧线。在此处输入图像描述

我使用以下代码创建了弧形背景:

// Method to convert degree to radians
num degToRad(num deg) => deg * (math.pi / 180.0);

// Paint
Paint paint = Paint()
  ..color = Grey
  ..style = PaintingStyle.stroke
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 10.0;

// Arc Path
Path path = Path();
path.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(180),degToRad(100));
path.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(288),degToRad(15));
path.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(311),degToRad(15));
path.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(334),degToRad(15));
path.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(357),degToRad(3));
canvas.drawPath(path, paint);

为了显示颜色动画,我在自定义画家中使用了以下逻辑:

// Paint
Paint paint2 = Paint()
  ..color = Purple
  ..style = PaintingStyle.stroke
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 10.0;


Path path2 = Path();
path2.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(180), animationValue);
path2.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(288), animationValue2);
path2.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(311), animationValue3);
path2.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(334), animationValue4);
path2.addArc(Rect.fromLTWH(0, 0, 250, 250), degToRad(357), animationValue5);

canvas.drawPath(path2, paint2);

以下是我用于动画的逻辑:

// First Arc
if (sweepAngleRad >= degToRad(100)) {
  arcAnimation = Tween<double>(begin: 0, end: degToRad(100)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
} 
else {
  arcAnimation = Tween<double>(begin: 0, end: sweepAngleRad).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}

// Second Arc with delay so as to match with the indicator animation
Future.delayed(Duration(milliseconds: 1150), () {
  if (sweepAngleRad >= degToRad(123)) {
    arcAnimation2 = Tween<double>(begin: 0, end: degToRad(15)).animate(_animationController)
    ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad <= degToRad(108)) {
   arcAnimation2 = Tween<double>(begin: 0, end: 0).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
} 
else if (sweepAngleRad >= degToRad(108) && sweepAngleRad <= degToRad(115.5)) {
  arcAnimation2 = Tween<double>(begin: 0, end: degToRad(3.75)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad >= degToRad(108) && sweepAngleRad <= degToRad(123)) {
   arcAnimation2 = Tween<double>(begin: 0, end: degToRad(9)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
});

// Third Arc with delay so as to match with the indicator animation
Future.delayed(Duration(milliseconds: 1300), () {
if (sweepAngleRad >= degToRad(146)) {
  arcAnimation3 = Tween<double>(begin: 0, end: degToRad(15)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad <= degToRad(131)) {
  arcAnimation3 = Tween<double>(begin: 0, end: 0).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad >= degToRad(131) && sweepAngleRad <= degToRad(138.5)) {
  arcAnimation3 = Tween<double>(begin: 0, end: degToRad(3.75)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad >= degToRad(131) && sweepAngleRad <= degToRad(146)) {
  arcAnimation3 = Tween<double>(begin: 0, end: degToRad(7.5)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
});

// Fourth Arc with delay so as to match with the indicator animation
Future.delayed(Duration(milliseconds: 1400), () {
if (sweepAngleRad >= degToRad(169)) {
  arcAnimation4 = Tween<double>(begin: 0, end: degToRad(15)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad <= degToRad(154)) {
  arcAnimation4 = Tween<double>(begin: 0, end: 0).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
 else if (sweepAngleRad >= degToRad(154) && sweepAngleRad <= degToRad(161.5)) {
  arcAnimation4 = Tween<double>(begin: 0, end: degToRad(3.75)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
else if (sweepAngleRad >= degToRad(154) && sweepAngleRad <= degToRad(169)) {
  arcAnimation4 = Tween<double>(begin: 0, end: degToRad(7.5)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
});

// Fifth Arc with delay so as to match with the indicator animation
Future.delayed(Duration(milliseconds: 1500), () {
if (sweepAngleRad >= degToRad(177)) {
  arcAnimation5 = Tween<double>(begin: 0, end: degToRad(3)).animate(_animationController)
  ..addListener(() {
    setState(() {});
  });
}
});

这就是指示动画的工作原理:

// Convert score to a corresponding angle in between 180-360
if (creditScore == 0) {
  scoreAngle = 180;
  sweepAngleRad = degToRad(1);
} else {
  scoreAngle = 180 + ((creditScore / 850) * 180);
  sweepAngleRad = degToRad(scoreAngle - 180);
}

final initialX = a + (r * math.cos(startAngleRad));
final initialY = b + (r * math.sin(startAngleRad));

Path path = Path();
path.moveTo(initialX, initialY);
path.arcTo(Rect.fromLTWH(0, 0, 250, 250), startAngleRad, sweepAngleRad, true);

Positioned(top: calculate(animation.value).dy,left: calculate(animation.value).dx,
            child: Container(decoration: BoxDecoration(border: Border.all(color: Purple, width: 5.0),shape: BoxShape.circle),
              child: Container(height: 10,width: 10,decoration: BoxDecoration(color: White, shape: BoxShape.circle)))),

Offset calculate(value) {
PathMetrics pathMetrics = _path.computeMetrics();
PathMetric pathMetric = pathMetrics.elementAt(0);
value = pathMetric.length * value;
Tangent pos = pathMetric.getTangentForOffset(value);
return pos.position;
}

现在弧正在填充,但不是按顺序填充的。我希望它在指示器通过弧线移动时填充。

4

0 回答 0