sketchDownload
// this program draws a 24/hour abacus that keeps track of day and time.
// each row of the abacus represents a different time-telling parameter:
var rowHeight = [-140, -74, -8, 58, 125]; // [month, day, hr, min, sec]
var rowColor;
var beadw = 7; // width of beads
// arrays will be filled with bead objects:
var monthBeads = [];
var dayBeads = [];
var hrBeads = [];
var minBeads = [];
var secBeads = [];
var resetMonth = [];
var resetDay = [];
var resetHr = [];
var resetMin = [];
var resetSec = [];
var allRows = [monthBeads, dayBeads, hrBeads, minBeads, secBeads];
function setup() {
createCanvas(480, 480);
background(220);
rectMode(CENTER);
rowColor = [color(145, 110, 205), // [month
color(200, 140, 205), // day
color(145, 140, 255), // hour
color(145, 185, 215), // minute
color(145, 200, 130)]; // second]
// populate monthBeads array with 12 beads:
for (i=0; i<12; i++) {
monthBeads[i] = {x: beadw*i, y: rowHeight[0]}
arrayCopy(monthBeads, resetMonth);
}
// populate dayBeads array with 31 beads:
for (i=0; i<31; i++) {
dayBeads[i] = {x: beadw*i, y: rowHeight[1]}
arrayCopy(dayBeads, resetDay);
}
// populate hrBeads array with 24 beads:
for (i=0; i<24; i++) {
hrBeads[i] = {x: beadw*i, y: rowHeight[2]}
arrayCopy(hrBeads, resetHr);
}
// populate minBeads array with 30 beads:
for (i=0; i<30; i++) {
minBeads[i] = {x: beadw*i, y: rowHeight[3]}
arrayCopy(minBeads, resetMin);
}
// populate secBeads array with 30 beads:
for (i=0; i<30; i++) {
secBeads[i] = {x: beadw*i, y: rowHeight[4]}
arrayCopy(secBeads, resetSec);
}
}
function draw() {
background(220);
//center canvas
translate(width/2, height/2);
// draw frame and rows of abacus
drawAbacus();
// draw all of the beads using the array for their row:
for (j=0; j<allRows.length; j++) {
setBeads(allRows[j]);
}
// check the time and move the beads accordingly:
moveBeads(monthBeads, month(), 0, resetMonth);
moveBeads(dayBeads, day(), 1, resetDay);
moveBeads(hrBeads, hour(), 2, resetHr);
moveBeads(minBeads, minute(), 3, resetMin);
moveBeads(secBeads, second(), 4, resetSec);
//noLoop();
}
//Draws the frame of the abacus:
function drawAbacus() {
fill(80, 55, 30);
//base:
quad(-195,190, 195,190, 220,215, -220,215);
quad(-195,190, 195,190, 200,200, -200,200);
quad(-200,200, 200,200, 220,220, -220,220);
//left post:
quad(-190,-200, -185,-210, -192,-210, -199,-200);
quad(-190,200, -185,190, -185,-210, -190,-200);
rect(-195, 0, 7, 400);
//right post:
quad(190,-200, 185,-210, 192,-210, 199,-200);
quad(190,200, 185,190, 185,-210, 190,-200);
rect(195, 0, 7, 400);
//rows for beads:
for (i=0; i<rowHeight.length; i++) {
rect(0, rowHeight[i], 375, 5);
}
//labels:
textSize(16);
textFont('monospace');
fill(0);
text('month', -181, rowHeight[0]+28);
text('day', -181, rowHeight[1]+28);
text('hour', -181, rowHeight[2]+28);
text('minute', -181, rowHeight[3]+28);
text('second', -181, rowHeight[4]+28);
}
// draws all of the beads into their rows
function setBeads(beadArray) {
fill(rowColor[j]); // color taken from for loop in draw function
strokeWeight(1.5);
for (i=0; i<beadArray.length; i++) {
if (beadArray.length == 31) { ellipse(beadArray[i].x-30, beadArray[i].y, beadw, 30) }
else if (beadArray.length == 30) { ellipse(beadArray[i].x-23, beadArray[i].y, beadw, 30) }
else if (beadArray.length == 24) { ellipse(beadArray[i].x+19, beadArray[i].y, beadw, 30) }
else if (beadArray.length == 12) { ellipse(beadArray[i].x+103, beadArray[i].y, beadw, 30) }
}
}
// checks time and moves the corresponding beads:
function moveBeads(row, func, ind, rowReset) {
var dist;
if (row.length == 12) {dist = 283 } //different distances based on number of beads in the row
if (row.length == 31) {dist = 150 }
if (row.length == 24) {dist = 199 }
if (row.length == 30) {dist = 157 }
for (i=0; i<func; i++) {
// the minutes and seconds beads will move every 2x they are passed bc it looks better like that:
if (dist == 157) {
row[i/2] = {x: beadw*i/2-dist, y: rowHeight[ind]}
} else {
row[i] = {x: beadw*i-dist, y: rowHeight[ind]}
}
// february has 28 days:
if (func == 28 & row.length == 31 && month()==2) { resetBeads(rowReset, monthBeads) }
// 30 days has september, april, june, and november:
if (func == 30 && row.length == 31 && month()==9) { resetBeads(rowReset, monthBeads) }
if (func == 30 && row.length == 31 && month()==4) { resetBeads(rowReset, monthBeads) }
if (func == 30 && row.length == 31 && month()==6) { resetBeads(rowReset, monthBeads) }
if (func == 30 && row.length == 31 && month()==11) { resetBeads(rowReset, monthBeads) }
}
// once the time parameter resets to 0, so do the beads:
if (func == 0) { resetBeads(rowReset, row) }
}
// sets the beads back to their original position, by row:
function resetBeads(rowReset, row) {
arrayCopy(rowReset, row);
}
This project took me way longer than I had hoped, but I am so so pleased with the outcome. After thinking about a few ideas, I decided to make an abacus because I think it would be very helpful for me personally to visualize time in that way. I struggled a lot to get the beads where they are supposed to go, but eventually I figured out how to use the arrayCopy function to my advantage.