I’m attempting to make a clock using p5js with 3 continuously rotating rings which have the current hour/minute/second at the top of each ring. At the moment I’m just trying to figure out the seconds ring, assuming I can work out the details for the other two rings from there. I’m able to initially draw all the numbers along the ring, and I can get the ring to rotate at the right pace, but the numbers don’t update correctly. I think I just need to update the number at the bottom, but I’m not sure how to handle it since the text
function doesn’t return any sort of manipulatable object. Any help would be greatly appreciated, as my head can’t take much more beating on the desk.
Here’s the relevant code. The white number in the corner is the current second. It’s just there for reference. As for the ring, I’m planning to hide the lower half off screen, so the disconnect at the bottom is intentional. It works if I fill it with all numbers 0-59, but trying to squeeze 60 numbers along the ring looks horrendous, hence why I’m hoping to only display the current second±12. The trueMod
function is the same as the %
operator, but handles negative numbers correctly.
// ring.js
class Ring {
/* radius: The radius of the ring.
* modulus: The modulus for the numbers along the ring.
* fillColor: The color of the ring.
* update: Function used to update the numbers.
*/
constructor(radius, modulus, fillColor, update) {
this.radius = radius;
this.modulus = modulus;
this.fillColor = fillColor;
this.update = update;
this.numSlices = 24; // number of numbers to display along the ring
}
draw() {
push();
fill(this.fillColor);
circle(0, 0, this.radius * 2 + 40);
rotate(millis() / 1000 * -TAU / this.numSlices);
fill(255);
let t = -TAU / 4;
let step = TAU / this.numSlices;
for (let i = 0; i < this.numSlices / 2; i++) {
push();
translate(this.radius * cos(t), this.radius * sin(t));
rotate(i * step);
text(
String(trueMod(this.update() + i, this.modulus)).padStart(2, "0"), 0, 0
);
t += step;
pop();
}
for (let i = this.numSlices / 2; i > 0; i--) {
push();
translate(this.radius * cos(t), this.radius * sin(t));
rotate(-i * step);
text(
String(trueMod(this.update() - i, this.modulus)).padStart(2, "0"), 0, 0
);
t += step;
pop();
}
pop();
}
}
// sketch.js
let secondRing;
function setup() {
createCanvas(windowWidth, windowHeight);
secondRing = new Ring(
windowHeight * 6 / 16,
60,
color(0x57, 0x75, 0x90),
second
);
}
function draw() {
background(0);
textAlign(CENTER, CENTER);
textSize((windowHeight * 1) / 30);
fill(255);
text(second(), 50, 50);
translate(windowWidth / 2, windowHeight / 2);
secondRing.draw();
}