
微信交流群
# 渐变进度圆环
自定义动画分为两种:组合动画 和 自绘动画。
组合动画就是多个组件或者多个动画控制器组成一个新的动画,就是将基础动画组件进行拼接的过程。
自绘动画就是使用 Canvas 进行绘制,并与动画控制器联动进行联动。
下面一步一步绘制渐变进度圆环,先根据进度绘制一个静态的圆环
class _CircleProgressPainter extends CustomPainter {
final double progress;
_CircleProgressPainter(this.progress);
Paint _paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 10
..color = Colors.blue;
void paint(Canvas canvas, Size size) {
double radius = min(size.width, size.height) / 2;
canvas.drawArc(Rect.fromLTWH(0, 0, radius * 2, radius * 2), -pi / 2,
pi * 2 * progress, false, _paint);
}
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
使用:
Container(
height: 150,
width: 150,
child: CustomPaint(
painter: _CircleProgressPainter(.3),
child: Center(child: Text('30%')),
),
)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
将蓝色修改为渐变色,_CircleProgressPainter修改如下:
void paint(Canvas canvas, Size size) {
double radius = min(size.width, size.height) / 2;
Gradient gradient = SweepGradient(
endAngle: pi * 2 * progress,
colors: [
Color(0xFFD32D2F),
Color(0xFFEA4886),
],
);
var rect = Rect.fromLTWH(0, 0, radius * 2, radius * 2);
_paint.shader = gradient.createShader(rect);
canvas.drawArc(Rect.fromLTWH(0, 0, radius * 2, radius * 2), -pi / 2,
pi * 2 * progress, false, _paint);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
发现渐变色是从水平方向开始的,而圆形进度是从垂直方向顶部开始,修改渐变色从垂直方向顶部开始:
Gradient gradient = SweepGradient(
startAngle: -pi / 2,
endAngle: pi * 2 * progress,
colors: [
Color(0xFFD32D2F),
Color(0xFFEA4886),
],
);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
渐变色设置 startAngle
参数,但却无效,效果没有发生变化,不知道是否是用法不对?因此只能换一个思路实现,旋转 canvas
,
void paint(Canvas canvas, Size size) {
double radius = min(size.width, size.height) / 2;
Gradient gradient = SweepGradient(
startAngle: -pi / 2,
endAngle: pi * 2 * progress,
colors: [
Color(0xFFD32D2F),
Color(0xFFEA4886),
],
);
var rect = Rect.fromLTWH(0, 0, radius * 2, radius * 2);
_paint.shader = gradient.createShader(rect);
canvas.save();
canvas.rotate(-pi / 2);
canvas.drawArc(Rect.fromLTWH(0, 0, radius * 2, radius * 2), -pi / 2,
pi * 2 * progress, false, _paint);
canvas.restore();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
画布的旋转是以左上角为原点,所以先向下平移,再旋转:
void paint(Canvas canvas, Size size) {
double radius = min(size.width, size.height) / 2;
Gradient gradient = SweepGradient(
startAngle: -pi / 2,
endAngle: pi * 2 * progress,
colors: [
Color(0xFFD32D2F),
Color(0xFFEA4886),
],
);
var rect = Rect.fromLTWH(0, 0, radius * 2, radius * 2);
_paint.shader = gradient.createShader(rect);
canvas.save();
canvas.translate(0.0, size.height);
canvas.rotate(-pi / 2);
canvas.drawArc(rect, 0, pi * 2 * progress, false, _paint);
canvas.restore();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
静态圆环绘制完成了,只需给其加上动画控制器,改变进度即可:
build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 150,
height: 150,
child: TweenAnimationBuilder(
tween: Tween(begin: 0.0, end: 1.0),
duration: Duration(seconds: 3),
builder: (BuildContext context, double value, Widget child) {
return CustomPaint(
painter: _CircleProgressPainter(value),
child: Center(child: Text('${(value * 100).floor()}%')),
);
},
),
),
),
);
}
Widget
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
进度圆环的两端是矩形,修改为圆形:
Paint _paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 10
..strokeCap = StrokeCap.round;
1
2
3
4
2
3
4
版权所有,禁止私自转发、克隆网站。