|
1
|
-import 'dart:math' show cos, min, pi, sin;
|
1
|
+import 'dart:math' show min, pi, asin;
|
|
2
|
|
2
|
|
|
3
|
import 'package:flutter/material.dart';
|
3
|
import 'package:flutter/material.dart';
|
|
4
|
|
4
|
|
|
@@ -48,7 +48,6 @@ class ProgressPainter extends CustomPainter { |
|
@@ -48,7 +48,6 @@ class ProgressPainter extends CustomPainter { |
|
48
|
var centerY = wh / 2;
|
48
|
var centerY = wh / 2;
|
|
49
|
var radius = wh / 2 - strokeWidth / 2;
|
49
|
var radius = wh / 2 - strokeWidth / 2;
|
|
50
|
|
50
|
|
|
51
|
- double startAngle = 0;
|
|
|
|
52
|
var rect = Rect.fromCenter(
|
51
|
var rect = Rect.fromCenter(
|
|
53
|
center: Offset(centerX, centerY),
|
52
|
center: Offset(centerX, centerY),
|
|
54
|
width: wh - strokeWidth,
|
53
|
width: wh - strokeWidth,
|
|
@@ -63,7 +62,7 @@ class ProgressPainter extends CustomPainter { |
|
@@ -63,7 +62,7 @@ class ProgressPainter extends CustomPainter { |
|
63
|
}
|
62
|
}
|
|
64
|
|
63
|
|
|
65
|
var shader = SweepGradient(
|
64
|
var shader = SweepGradient(
|
|
66
|
- startAngle: startAngle.toRadians(),
|
65
|
+ startAngle: 0.toRadians(),
|
|
67
|
endAngle: 360.toRadians(),
|
66
|
endAngle: 360.toRadians(),
|
|
68
|
colors: reverse
|
67
|
colors: reverse
|
|
69
|
? progressColor[colorRangeIndex].reversed.toList()
|
68
|
? progressColor[colorRangeIndex].reversed.toList()
|
|
@@ -82,11 +81,6 @@ class ProgressPainter extends CustomPainter { |
|
@@ -82,11 +81,6 @@ class ProgressPainter extends CustomPainter { |
|
82
|
..strokeCap = StrokeCap.butt
|
81
|
..strokeCap = StrokeCap.butt
|
|
83
|
..style = PaintingStyle.stroke;
|
82
|
..style = PaintingStyle.stroke;
|
|
84
|
|
83
|
|
|
85
|
- var startCapPosition = Offset(
|
|
|
|
86
|
- centerX + radius * cos(startAngle.toRadians()),
|
|
|
|
87
|
- centerY + radius * sin(startAngle.toRadians()),
|
|
|
|
88
|
- );
|
|
|
|
89
|
-
|
|
|
|
90
|
canvas.drawArc(
|
84
|
canvas.drawArc(
|
|
91
|
rect,
|
85
|
rect,
|
|
92
|
0.toRadians(),
|
86
|
0.toRadians(),
|
|
@@ -94,7 +88,31 @@ class ProgressPainter extends CustomPainter { |
|
@@ -94,7 +88,31 @@ class ProgressPainter extends CustomPainter { |
|
94
|
false,
|
88
|
false,
|
|
95
|
backgroundPaint,
|
89
|
backgroundPaint,
|
|
96
|
);
|
90
|
);
|
|
|
|
91
|
+
|
|
97
|
if (sweepAngle >= 0) {
|
92
|
if (sweepAngle >= 0) {
|
|
|
|
93
|
+ double capAngle = 0;
|
|
|
|
94
|
+ if (radius > 0) {
|
|
|
|
95
|
+ capAngle = asin((strokeWidth / 2) / radius) * 180 / pi;
|
|
|
|
96
|
+ }
|
|
|
|
97
|
+
|
|
|
|
98
|
+ double actualCapAngle = capAngle;
|
|
|
|
99
|
+ if (sweepAngle < 360) {
|
|
|
|
100
|
+ if (sweepAngle < 2 * capAngle) {
|
|
|
|
101
|
+ actualCapAngle = sweepAngle / 2;
|
|
|
|
102
|
+ }
|
|
|
|
103
|
+ } else {
|
|
|
|
104
|
+ actualCapAngle = 0;
|
|
|
|
105
|
+ }
|
|
|
|
106
|
+
|
|
|
|
107
|
+ double startAngle = actualCapAngle;
|
|
|
|
108
|
+ double drawnSweepAngle = sweepAngle;
|
|
|
|
109
|
+ if (sweepAngle < 360) {
|
|
|
|
110
|
+ drawnSweepAngle = sweepAngle - 2 * actualCapAngle;
|
|
|
|
111
|
+ if (drawnSweepAngle < 0) {
|
|
|
|
112
|
+ drawnSweepAngle = 0;
|
|
|
|
113
|
+ }
|
|
|
|
114
|
+ }
|
|
|
|
115
|
+
|
|
98
|
canvas.save();
|
116
|
canvas.save();
|
|
99
|
// Move the canvas origin to the center
|
117
|
// Move the canvas origin to the center
|
|
100
|
canvas.translate(centerX, centerY);
|
118
|
canvas.translate(centerX, centerY);
|
|
@@ -111,9 +129,12 @@ class ProgressPainter extends CustomPainter { |
|
@@ -111,9 +129,12 @@ class ProgressPainter extends CustomPainter { |
|
111
|
canvas.translate(-centerX, -centerY);
|
129
|
canvas.translate(-centerX, -centerY);
|
|
112
|
|
130
|
|
|
113
|
if (sweepAngle < 360) {
|
131
|
if (sweepAngle < 360) {
|
|
|
|
132
|
+ canvas.save();
|
|
|
|
133
|
+ canvas.translate(centerX, centerY);
|
|
|
|
134
|
+ canvas.rotate(reverse ? -startAngle.toRadians() : startAngle.toRadians());
|
|
114
|
canvas.drawArc(
|
135
|
canvas.drawArc(
|
|
115
|
Rect.fromCenter(
|
136
|
Rect.fromCenter(
|
|
116
|
- center: startCapPosition,
|
137
|
+ center: Offset(radius, 0),
|
|
117
|
width: strokeWidth,
|
138
|
width: strokeWidth,
|
|
118
|
height: strokeWidth,
|
139
|
height: strokeWidth,
|
|
119
|
),
|
140
|
),
|
|
@@ -122,76 +143,73 @@ class ProgressPainter extends CustomPainter { |
|
@@ -122,76 +143,73 @@ class ProgressPainter extends CustomPainter { |
|
122
|
true,
|
143
|
true,
|
|
123
|
Paint()..color = progressColor[0].first,
|
144
|
Paint()..color = progressColor[0].first,
|
|
124
|
);
|
145
|
);
|
|
|
|
146
|
+ canvas.drawRect(
|
|
|
|
147
|
+ Rect.fromCenter(
|
|
|
|
148
|
+ center: Offset(radius, 0),
|
|
|
|
149
|
+ width: strokeWidth,
|
|
|
|
150
|
+ height: 1,
|
|
|
|
151
|
+ ),
|
|
|
|
152
|
+ Paint()..color = progressColor[0].first,
|
|
|
|
153
|
+ );
|
|
|
|
154
|
+ canvas.restore();
|
|
125
|
}
|
155
|
}
|
|
|
|
156
|
+
|
|
126
|
canvas.drawArc(
|
157
|
canvas.drawArc(
|
|
127
|
rect,
|
158
|
rect,
|
|
128
|
- 0.toRadians(),
|
159
|
+ reverse ? -startAngle.toRadians() : startAngle.toRadians(),
|
|
129
|
reverse
|
160
|
reverse
|
|
130
|
- ? -(startAngle + sweepAngle).toRadians()
|
|
|
|
131
|
- : (startAngle + sweepAngle).toRadians(),
|
161
|
+ ? -drawnSweepAngle.toRadians()
|
|
|
|
162
|
+ : drawnSweepAngle.toRadians(),
|
|
132
|
false,
|
163
|
false,
|
|
133
|
paint,
|
164
|
paint,
|
|
134
|
);
|
165
|
);
|
|
135
|
- if (sweepAngle < 360) {
|
166
|
+
|
|
|
|
167
|
+ if (sweepAngle != 360) {
|
|
|
|
168
|
+ final endAngle = startAngle + drawnSweepAngle;
|
|
|
|
169
|
+ canvas.save();
|
|
|
|
170
|
+ canvas.translate(centerX, centerY);
|
|
|
|
171
|
+ canvas.rotate(reverse ? -endAngle.toRadians() : endAngle.toRadians());
|
|
|
|
172
|
+
|
|
|
|
173
|
+ final endColor =
|
|
|
|
174
|
+ getColorAtAngle(sweepAngle, progressColor[colorRangeIndex]);
|
|
|
|
175
|
+
|
|
|
|
176
|
+ final bool shouldDrawShadow = sweepAngle > 360 || (sweepAngle > 355 && sweepAngle < 360);
|
|
|
|
177
|
+ if (shouldDrawShadow) {
|
|
|
|
178
|
+ //Draw arc shadow
|
|
|
|
179
|
+ var shadowPosition = Offset(
|
|
|
|
180
|
+ radius,
|
|
|
|
181
|
+ reverse ? -4 : 4,
|
|
|
|
182
|
+ );
|
|
|
|
183
|
+ final Paint shadowPaint = Paint()
|
|
|
|
184
|
+ ..color = Colors.black.withOpacity(0.35)
|
|
|
|
185
|
+ ..style = PaintingStyle.fill
|
|
|
|
186
|
+ ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 3);
|
|
|
|
187
|
+ canvas.drawCircle(shadowPosition, strokeWidth / 2, shadowPaint);
|
|
|
|
188
|
+ }
|
|
|
|
189
|
+
|
|
|
|
190
|
+ //Draw the ending arc
|
|
|
|
191
|
+ canvas.drawArc(
|
|
|
|
192
|
+ Rect.fromCenter(
|
|
|
|
193
|
+ center: Offset(radius, 0),
|
|
|
|
194
|
+ width: strokeWidth,
|
|
|
|
195
|
+ height: strokeWidth,
|
|
|
|
196
|
+ ),
|
|
|
|
197
|
+ 0,
|
|
|
|
198
|
+ reverse ? -180.toRadians() : 180.toRadians(),
|
|
|
|
199
|
+ true,
|
|
|
|
200
|
+ Paint()..color = endColor,
|
|
|
|
201
|
+ );
|
|
136
|
canvas.drawRect(
|
202
|
canvas.drawRect(
|
|
137
|
Rect.fromCenter(
|
203
|
Rect.fromCenter(
|
|
138
|
- center: startCapPosition,
|
204
|
+ center: Offset(radius, 0),
|
|
139
|
width: strokeWidth,
|
205
|
width: strokeWidth,
|
|
140
|
height: 1,
|
206
|
height: 1,
|
|
141
|
),
|
207
|
),
|
|
142
|
- Paint()..color = progressColor[0].first,
|
208
|
+ Paint()..color = endColor,
|
|
143
|
);
|
209
|
);
|
|
|
|
210
|
+ canvas.restore();
|
|
144
|
}
|
211
|
}
|
|
145
|
|
212
|
|
|
146
|
- canvas.translate(centerX, centerY);
|
|
|
|
147
|
- if (sweepAngle < 360) {
|
|
|
|
148
|
- final endCapRotate = 360 - sweepAngle;
|
|
|
|
149
|
- canvas.rotate(
|
|
|
|
150
|
- reverse ? endCapRotate.toRadians() : -endCapRotate.toRadians());
|
|
|
|
151
|
- }
|
|
|
|
152
|
- //0.1 is because the angle calculation is not accurate enough, so we need to go back a little bit.
|
|
|
|
153
|
- var endCapPosition = Offset(
|
|
|
|
154
|
- centerX + radius * cos((startAngle).toRadians()),
|
|
|
|
155
|
- centerY + radius * sin((startAngle).toRadians()),
|
|
|
|
156
|
- );
|
|
|
|
157
|
-
|
|
|
|
158
|
- canvas.translate(-centerX, -centerY);
|
|
|
|
159
|
- final endColor =
|
|
|
|
160
|
- getColorAtAngle(sweepAngle, progressColor[colorRangeIndex]);
|
|
|
|
161
|
- if (sweepAngle > 355) {
|
|
|
|
162
|
- //Draw arc shadow
|
|
|
|
163
|
- var shadowPosition = Offset(
|
|
|
|
164
|
- centerX + radius * cos((startAngle).toRadians()),
|
|
|
|
165
|
- centerY + (reverse ? -4 : 4) + radius * sin((startAngle).toRadians()),
|
|
|
|
166
|
- );
|
|
|
|
167
|
- final Paint shadowPaint = Paint()
|
|
|
|
168
|
- ..color = Colors.black.withOpacity(0.35)
|
|
|
|
169
|
- ..style = PaintingStyle.fill
|
|
|
|
170
|
- ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 3);
|
|
|
|
171
|
- canvas.drawCircle(shadowPosition, strokeWidth / 2, shadowPaint);
|
|
|
|
172
|
- }
|
|
|
|
173
|
-
|
|
|
|
174
|
- //Draw the ending arc
|
|
|
|
175
|
- canvas.drawArc(
|
|
|
|
176
|
- Rect.fromCenter(
|
|
|
|
177
|
- center: endCapPosition,
|
|
|
|
178
|
- width: strokeWidth,
|
|
|
|
179
|
- height: strokeWidth,
|
|
|
|
180
|
- ),
|
|
|
|
181
|
- 0,
|
|
|
|
182
|
- reverse ? -180.toRadians() : 180.toRadians(),
|
|
|
|
183
|
- true,
|
|
|
|
184
|
- Paint()..color = endColor,
|
|
|
|
185
|
- );
|
|
|
|
186
|
- canvas.drawRect(
|
|
|
|
187
|
- Rect.fromCenter(
|
|
|
|
188
|
- center: endCapPosition,
|
|
|
|
189
|
- width: strokeWidth,
|
|
|
|
190
|
- height: 1,
|
|
|
|
191
|
- ),
|
|
|
|
192
|
- Paint()..color = endColor,
|
|
|
|
193
|
- );
|
|
|
|
194
|
-
|
|
|
|
195
|
// // Restore the canvas to the saved state
|
213
|
// // Restore the canvas to the saved state
|
|
196
|
canvas.restore();
|
214
|
canvas.restore();
|
|
197
|
}
|
215
|
}
|