弧线是使用 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;
}
现在弧正在填充,但不是按顺序填充的。我希望它在指示器通过弧线移动时填充。