-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclock2.html
More file actions
150 lines (134 loc) · 3.58 KB
/
clock2.html
File metadata and controls
150 lines (134 loc) · 3.58 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
150
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>6-Gear Binary Watch with Winding</title>
<style>
body {
background: #000;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
font-family: monospace;
}
canvas {
background: #111;
border: 2px solid #fff;
border-radius: 50%;
cursor: grab;
}
</style>
</head>
<body>
<canvas id="watch" width="400" height="400"></canvas>
<script>
// ------------------------
// Settings
const totalGears = 6;
const canvas = document.getElementById('watch');
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 180;
// Gear ratios (G1->G2->...->G6)
const gearRatios = [
[40,60], // G1->G2
[48,40], // G2->G3
[1,1], // G3->G4 (compound)
[30,60], // G4->G5
[60,30] // G5->G6
];
// ------------------------
// Fixed-point helpers
const FIXED_BITS = 32;
const FIXED_SCALE = 1 << FIXED_BITS;
function toFixed(numerator, denominator) {
return Math.floor((numerator / denominator) * FIXED_SCALE);
}
function fromFixed(value) {
return value / FIXED_SCALE;
}
// Input rotation per ns (G1: 1 rotation per 60s)
const nsPerSecond = 1e9;
const inputRotPerNs = toFixed(1, 60*nsPerSecond);
// ------------------------
// Watch state
let g1Rotation = 0; // G1 rotation in fixed-point (can be increased by winding)
let isDragging = false;
let lastY = 0;
// ------------------------
// Mouse / touch interaction for winding
canvas.addEventListener('mousedown', e => {
isDragging = true;
lastY = e.clientY;
canvas.style.cursor = 'grabbing';
});
canvas.addEventListener('mouseup', e => isDragging = false);
canvas.addEventListener('mouseleave', e => isDragging = false);
canvas.addEventListener('mousemove', e => {
if(isDragging){
const delta = lastY - e.clientY;
g1Rotation += delta * 0.005 * FIXED_SCALE; // scale winding speed
lastY = e.clientY;
}
});
// Touch support
canvas.addEventListener('touchstart', e => {
isDragging = true;
lastY = e.touches[0].clientY;
});
canvas.addEventListener('touchend', e => isDragging = false);
canvas.addEventListener('touchmove', e => {
if(isDragging){
const delta = lastY - e.touches[0].clientY;
g1Rotation += delta * 0.005 * FIXED_SCALE;
lastY = e.touches[0].clientY;
e.preventDefault();
}
});
// ------------------------
// Animation loop
let startTime = null;
function drawWatch(timestamp) {
if (!startTime) startTime = timestamp;
const elapsedMs = timestamp - startTime;
const elapsedNs = elapsedMs * 1e6; // convert ms to ns
ctx.clearRect(0,0,canvas.width,canvas.height);
// G1 rotation due to time
let rot = g1Rotation + inputRotPerNs * elapsedNs;
let prevRot = rot;
for (let i = 0; i < totalGears; i++) {
// Apply gear ratio from previous gear
if(i>0){
prevRot = (prevRot * toFixed(gearRatios[i-1][0], gearRatios[i-1][1])) >> FIXED_BITS;
// Optional: invert rotation for meshing gears
// prevRot = -prevRot;
}
let rotTurn = fromFixed(prevRot); // rotation in turns
let angle = rotTurn * 2*Math.PI; // radians
// draw gear circle
let r = radius - i*25;
ctx.beginPath();
ctx.arc(centerX, centerY, r, 0, 2*Math.PI);
ctx.strokeStyle = `hsl(${i*60}, 100%, 50%)`;
ctx.lineWidth = 4;
ctx.stroke();
// draw gear hand
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.lineTo(centerX + r*Math.cos(angle - Math.PI/2),
centerY + r*Math.sin(angle - Math.PI/2));
ctx.strokeStyle = '#fff';
ctx.lineWidth = 2;
ctx.stroke();
}
requestAnimationFrame(drawWatch);
}
requestAnimationFrame(drawWatch);
</script>
</body>
</html>