-
Notifications
You must be signed in to change notification settings - Fork 0
/
progress-circle.view.ts
78 lines (67 loc) · 2.36 KB
/
progress-circle.view.ts
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { degreesToRadians, getPointAtAngle, getRelativeControlPoints } from '../utils/arc.utils';
export const addArc = (
path: Path,
fromPercentage: number,
toPercentage: number,
center: Point,
radius: number
) => {
const fromRadians = degreesToRadians(360 * fromPercentage);
const toRadians = degreesToRadians(360 * toPercentage);
const start = getPointAtAngle(fromRadians, center, radius);
const end = getPointAtAngle(toRadians, center, radius);
const controls = getRelativeControlPoints(fromRadians, toRadians, center, radius);
path.move(start);
path.addCurve(end, ...controls);
};
export const addCap = (context: DrawContext, size: number, point: Point) => {
context.fillEllipse(new Rect(point.x - size / 2, point.y - size / 2, size, size));
};
export const createProgressCircle = (
percentage: number,
background: Color,
foreground: Color,
labelColor: Color,
label = '',
font = 25,
size = 100,
stroke = 10
): DrawContext => {
const center = new Point(size / 2, size / 2);
const radius = (size - stroke) / 2;
const assumedLineHeight = 1.25;
// prepare draw context
const path = new Path();
const context = new DrawContext();
context.opaque = false;
context.respectScreenScale = true;
context.size = new Size(size, size);
context.setLineWidth(stroke);
// draw background circle
context.setStrokeColor(background);
context.strokeEllipse(new Rect(stroke / 2, stroke / 2, size - stroke, size - stroke));
// draw arc (and split if exceeding 180°)
context.setStrokeColor(foreground);
if (percentage > 0.5) {
addArc(path, 0, 0.5, center, radius);
addArc(path, 0.5, percentage, center, radius);
} else {
addArc(path, 0, percentage, center, radius);
}
// add path to context and add the stroke
context.addPath(path);
context.strokePath();
// add rounded caps
context.setFillColor(foreground);
addCap(context, stroke, getPointAtAngle(degreesToRadians(0), center, radius));
addCap(context, stroke, getPointAtAngle(degreesToRadians(360 * percentage), center, radius));
// add label
const innerSize = size - stroke * 2;
const y = (size - font * assumedLineHeight) / 2;
context.setTextAlignedCenter();
context.setTextColor(labelColor);
context.setFont(Font.mediumSystemFont(font));
context.drawTextInRect(label, new Rect(stroke, y, innerSize, innerSize));
// deliver result
return context;
};