-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
149 lines (127 loc) · 3.71 KB
/
Copy pathmain.js
File metadata and controls
149 lines (127 loc) · 3.71 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* @type {HTMLCanvasElement | null}
*/
let canvas = null;
/**
* @type {CanvasRenderingContext2D | null}
*/
let ctx = null;
let lastDate = null;
const play = () => {
if (!canvas) return;
if (!ctx) {
ctx = canvas.getContext("2d");
}
// Draw the canvas
draw();
// Start the game loop
requestAnimationFrame(play);
};
/**
* Gets the center of the canvas
* @returns {{x: number, y: number}}
*/
const getCenter = () => {
return { x: canvas.width / 2, y: canvas.height / 2 };
};
const relative = (x) => {
return canvas.width / 400 * x;
}
const draw = () => {
if (!ctx) return;
ctx.textAlign = "center";
ctx.textBaseline = "middle"
const now = new Date();
// If the seconds are the same, don't draw
if (lastDate && lastDate.getSeconds() === now.getSeconds()) {
return;
}
lastDate = now;
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
const center = getCenter();
// Draw marks
drawMarks();
// Draw circle at center
drawCircle(center, 5);
const centerOffset = -4;
// Draw second hand
drawHand(centerOffset, 12, "Arial Light", now.getSeconds(), now.getSeconds() / 60, 10, 4);
// Draw minute hand
drawHand(centerOffset, 18, "Arial", now.getMinutes(), now.getMinutes() / 60, 7, 4);
// Draw hour hand
drawHand(centerOffset, 18, "Arial Black", now.getHours(), now.getHours() % 12 / 12, 5, 0);
};
const drawMarks = () => {
const center = getCenter();
const radius = relative(200);
for (let i = 0; i < 60; i++) {
const isHour = i % 5 == 0;
const width = isHour ? 3 : 2;
const length = relative(isHour ? 170 : 190);
const angle = Math.PI * 2 * i / 60 - Math.PI / 2;
const angleCosine = Math.cos(angle);
const angleSine = Math.sin(angle);
const start = {
x: center.x + angleCosine * radius,
y: center.y + angleSine * radius
};
const end = {
x: center.x + angleCosine * length,
y: center.y + angleSine * length
};
ctx.lineWidth = relative(width);
drawLine(start, end);
}
}
const drawLine = (start, end) => {
ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
const drawCircle = (center, radius) => {
ctx.beginPath();
ctx.arc(center.x, center.y, relative(radius), 0, Math.PI * 2);
ctx.fill();
}
const drawHand = (fromCenterDistance, fontSize, font, value, percentage, sequenceLength, spacing) => {
// Set the font
ctx.font = `${relative(fontSize)}px ${font}`;
// Calculate the angle
const angleInRadians = Math.PI * 2 * percentage - Math.PI / 2;
// Calculate the cosine and sine of the angle
const angleCosine = Math.cos(angleInRadians);
const angleSine = Math.sin(angleInRadians);
// Calculate the start position
const center = getCenter();
const radiusFromCenter = relative(fromCenterDistance);
let start = {
x: center.x + angleCosine * radiusFromCenter,
y: center.y + angleSine * radiusFromCenter
};
// Draw the text and calculate the next positions
for (i = 0; i < sequenceLength; i++) {
start.x += angleCosine * relative(fontSize + spacing);
start.y += angleSine * relative(fontSize + spacing);
ctx.fillText(value, start.x, start.y);
}
}
// Invoked when the DOM is fully loaded
const onLoad = () => {
canvas = document.querySelector("canvas");
onResize(); // Set the initial size
play(); // Start the game loop
};
const onResize = () => {
if (!canvas) return;
const { innerWidth, innerHeight } = window;
const size = Math.min(innerWidth, innerHeight);
const scale = 0.9;
canvas.width = size * scale;
canvas.height = size * scale;
lastDate = null; // Force redraw
}
// Assign the listeners
window.addEventListener("DOMContentLoaded", onLoad);
window.addEventListener("resize", onResize);