Skip to content

Instantly share code, notes, and snippets.

@dribnet
Last active March 19, 2018 23:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dribnet/db72032317305dea2cee2fc780853329 to your computer and use it in GitHub Desktop.
Save dribnet/db72032317305dea2cee2fc780853329 to your computer and use it in GitHub Desktop.
MDDN 242 Assignment 1: Clock

PS1 MDDN 242 2017

Examples of technique

How to use p5.js API and JavaScript bits.

/*
* us p5.js to draw a clock on a 960x500 canvas
*/
function draw_ovals(pos_x) {
ellipse(pos_x, 100, 10, 10);
ellipse(pos_x, 200, 10, 10);
}
function draw_clock(obj) {
// draw your own clock here based on the values of obj:
// obj.hours goes from 0-23
// obj.minutes goes from 0-59
// obj.seconds goes from 0-59
// obj.millis goes from 0-1000
// obj.seconds_until_alarm is:
// < 0 if no alarm is set
// = 0 if the alarm is currently going off
// > 0 --> the number of seconds until alarm should go off
let hours = obj.hours;
let minutes = obj.minutes;
let seconds = obj.seconds;
let millis = obj.millis;
let seconds_until_alarm = obj.seconds_until_alarm;
// background(200);
// fill(200);
// rect(100, 100, 200, 200);
// let a = map(30, 0, 100, 0, 10);
// console.log(a);
// let sum = 0;
// background(0);
// fill(255);
// for (let i = 0; i < 100; i = i+10) {
// rect(i, 100, 5, 5);
// }
// console.log(sum)
draw_ovals(100);
draw_ovals(200);
draw_ovals(300);
// const BACK_COLOR=0;
// background(BACK_COLOR);
// const start_y = 300;
// const end_y = 400;
// fill(0, 0, 255);
// rect(0, start_y, width, 5);
// fill(0, 255, 0);
// rect(0, end_y, width, 5);
// fill(200);
// stroke(60);
// let cur_pos = map(millis, 0, 1000, start_y, end_y);
// for(let x=100; x<=600; x = x + 100) {
// rect(x, cur_pos, 50, 50);
// }
// draw_ovals(200, cur_pos);
}
// function draw_ovals(start_x, cur_y) {
// for(let x=start_x; x<=600; x = x + 100) {
// ellipse(x, cur_y, 50, 50);
// }
// }
const CANVAS_WIDTH = 960;
const CANVAS_HEIGHT = 500;
function setup () {
// create the drawing canvas, save the canvas element
let main_canvas = createCanvas(CANVAS_WIDTH, CANVAS_HEIGHT);
main_canvas.parent('canvasContainer');
// you can optionally add your own code here if you also have setup code
}
// Update this function to draw you own maeda clock
function draw () {
fill(0);
background(0);
strokeWeight(5);
const spacing = 100;
stroke(255, 0, 0);
for(let i = -2*spacing; i <= 2*spacing; i = i+spacing) {
ellipse(width/2, height/2+i, 45, 45);
}
strokeWeight(3);
stroke(255, 255, 0);
for(let i = -2*spacing; i <= 2*spacing; i = i+spacing) {
ellipse(width/2, height/2+i, 40, 40);
}
stroke(0, 0, 255);
for(let i = -2*spacing; i <= 2*spacing; i = i+spacing) {
ellipse(width/2, height/2+i, 30, 30);
}
}
// do not alter or remove this function
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
}
/*
* us p5.js to draw a clock on a 960x500 canvas
*/
function draw_clock(obj) {
// draw your own clock here based on the values of obj:
// obj.hours goes from 0-23
// obj.minutes goes from 0-59
// obj.seconds goes from 0-59
// obj.millis goes from 0-999
// obj.seconds_until_alarm is:
// < 0 if no alarm is set
// = 0 if the alarm is currently going off
// > 0 --> the number of seconds until alarm should go off
let hours = obj.hours;
let minutes = obj.minutes;
let seconds = obj.seconds;
let millis = obj.millis;
background(255,255,200); // beige
fill(128,100,100); // dark grey
text("Hour: " + hours, 10, 22);
text("Minute: " + minutes, 10, 42);
text("Second: " + seconds, 10, 62);
text("Millis: " + millis, 10, 82);
let hourBarWidth = map(hours, 0, 23, 0, width);
let minuteBarWidth = map(minutes, 0, 59, 0, width);
let secondBarWidth = map(seconds, 0, 59, 0, width);
let millisBarWidth = map(millis, 0, 1000, 0, width);
noStroke();
fill(40);
rect(0, 100, hourBarWidth, 50);
fill(80);
rect(0, 150, minuteBarWidth, 50);
fill(120)
rect(0, 200, secondBarWidth, 50);
fill(160)
rect(0, 250, millisBarWidth, 50);
// Make a bar which *smoothly* interpolates across 1 minute.
// We calculate a version that goes from 0...60,
// but with a fractional remainder:
let secondBarWidthChunky = map(seconds, 0, 60, 0, width);
let secondsWithFraction = seconds + (millis / 1000.0);
let secondBarWidthSmooth = map(secondsWithFraction, 0, 60, 0, width);
fill(100, 100, 200)
rect(0, 350, secondBarWidthChunky, 50);
fill(120, 120, 240)
rect(0, 400, secondBarWidthSmooth, 50);
text("Minute: " + secondsWithFraction, 200, 42);
}
/*
* us p5.js to draw a clock on a 960x500 canvas
*/
/* size of square */
var s = 24
var numbers = [
// 0
[
[2, 1],
[3, 1],
[1, 2],
[4, 2],
[1, 3],
[4, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
],
// 1
[
[2, 2],
[3, 1],
[3, 2],
[3, 3],
[3, 4],
[3, 5]
],
// 2
[
[1, 1],
[2, 1],
[3, 1],
[4, 2],
[4, 3],
[3, 3],
[2, 4],
[1, 5],
[2, 5],
[3, 5],
[4, 5]
],
[ // 3
[1, 1],
[2, 1],
[3, 1],
[4, 2],
[3, 3],
[2, 3],
[4, 4],
[3, 5],
[2, 5],
[1, 5]
],
[ // 4
[1, 1],
[3, 1],
[1, 2],
[3, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 3],
[3, 4],
[3, 5]
],
[ // 5
[1, 1],
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 4],
[3, 5],
[2, 5],
[1, 5]
],
[ // 6
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[1, 3],
[2, 3],
[3, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
], //7
[
[1, 1],
[2, 1],
[3, 1],
[4, 1],
[4, 2],
[3, 3],
[3, 4],
[3, 5],
],
[ // 8
[2, 1],
[3, 1],
[1, 2],
[4, 2],
[2, 3],
[3, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
],
[ // 9
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[4, 2],
[2, 3],
[3, 3],
[4, 3],
[4, 4],
[4, 5]
],
]
function draw_number(num, x, y) {
/* this resets any previous translations */
resetMatrix();
translate(x, y);
var pixels = numbers[num%numbers.length];
for(var i=0; i<13; i++) {
var cur_pixel = pixels[i%pixels.length];
rect(cur_pixel[0] * s, cur_pixel[1] * s, s, s);
}
}
function draw_number_interp(frac, num1, num2, x, y) {
/* this resets any previous translations */
resetMatrix();
translate(x, y);
var pixels1 = numbers[num1%numbers.length];
var pixels2 = numbers[num2%numbers.length];
for(var i=0; i<13; i++) {
var cur_pixel1 = pixels1[i%pixels1.length];
var cur_pixel2 = pixels2[i%pixels2.length];
var pos_x = map(frac, 0.0, 1.0, cur_pixel1[0], cur_pixel2[0]);
var pos_y = map(frac, 0.0, 1.0, cur_pixel1[1], cur_pixel2[1]);
rect(pos_x * s, pos_y * s, s, s);
}
}
function digits_from_num(num) {
digits = []
if (num < 10) {
digits.push(0);
}
else {
n1 = Math.floor(num / 10);
digits.push(n1);
}
n2 = Math.floor(num % 10);
digits.push(n2);
return digits;
}
function draw_clock(obj) {
let hour = obj.hours;
let minute = obj.minutes;
let second = obj.seconds;
let millis = obj.millis;
let alarm = obj.seconds_until_alarm;
var hour_pos = [40, height/2 - 3.5 * s];
// DEBUG CODE TO TEST HOUR ROLLOVER
// minute = minute + 35; // change based on current time
// if (minute == 60) {
// minute = 0;
// hour = 0;
// }
// is alarm going off?
if (alarm == 0) {
if (second % 2 == 0) {
background(0,0,100);
}
else {
background(100,100,0);
}
}
else {
background(50);
}
noStroke();
// is alarm going off in next 15 seconds
if (alarm > 0) {
fill(100);
rect(width-50, height-50, 40, 40);
if (alarm < 15.0) {
var box_w = map(alarm, 0, 15, width, 0);
var box_h = map(alarm, 0, 15, height, 0);
rect(width/2-box_w/2, height/2-box_h/2, box_w, box_h);
}
}
fill(255);
// HOURS
next_hour = (hour + 1) % 24;
digits1 = digits_from_num(hour);
digits2 = digits_from_num(next_hour);
if(second >= 50 && minute == 59 &&
(hour == 9 || hour == 19 || hour == 23)) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 50) + millis / 1000.0;
hour_fraction_tens = seconds_left / 10.0;
}
else {
hour_fraction_tens = 0;
}
draw_number_interp(hour_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 0.0 * 5 * s, hour_pos[1]);
// draw_number(digits1[0], hour_pos[0], hour_pos[1]);
if(second >= 55 && minute == 59) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 55) + millis / 1000.0;
hour_fraction_ones = seconds_left / 5.0;
}
else {
hour_fraction_ones = 0;
}
draw_number_interp(hour_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 1.0 * 5 * s, hour_pos[1]);
// draw_number(digits1[1], hour_pos[0] + 1.0 * 5 * s, hour_pos[1]);
// MINUTES
next_minute = (minute + 1) % 60;
digits1 = digits_from_num(minute);
digits2 = digits_from_num(next_minute);
if(second >= 58 && digits1[1] === 9) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 58) + millis / 1000.0;
minute_fraction_tens = seconds_left / 2.0;
}
else {
minute_fraction_tens = 0;
}
draw_number_interp(minute_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 2.5 * 5 * s, hour_pos[1]);
if(second === 59) {
minute_fraction_ones = millis / 1000.0;
}
else {
minute_fraction_ones = 0;
}
draw_number_interp(minute_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 3.5 * 5 * s, hour_pos[1]);
// draw_number(digits1[1], hour_pos[0] + 3.5 * 5 * s, hour_pos[1]);
// SECONDS
next_second = (second + 1) % 60;
second_fraction = millis / 1000.0;
digits1 = digits_from_num(second);
digits2 = digits_from_num(next_second);
if(digits1[1] === 9 && millis > 500) {
second_fraction_tens = (millis - 500) / 500.0;
}
else {
second_fraction_tens = 0;
}
// draw the 10 second position
draw_number_interp(second_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 5.0 * 5 * s, hour_pos[1]);
if(millis > 900) {
second_fraction_ones = (millis-900) / 100.0;
}
else {
second_fraction_ones = 0;
}
// draw the 1 second position
draw_number_interp(second_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 6.0 * 5 * s, hour_pos[1]);
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="debug.js"></script>
<script language="javascript" type="text/javascript" src="clock.js"></script>
<script language="javascript" type="text/javascript" src="runner.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
<div class="inner" id="controls">
<table>
<tr>
<td>debug</td>
<td id="checkboxDebug"></td>
</tr>
<tr>
<td>hours</td>
<td id="sliderHours"></td>
<td>minutes</td>
<td id="sliderMinutes"></td>
<td>seconds</td>
<td id="sliderSeconds"></td>
<td>millis</td>
<td id="sliderMillis"></td>
</tr>
<tr>
<td>alarm</td>
<td id="checkboxAlarm"></td>
<td>alarm_secs</td>
<td id="sliderAlarm"></td>
</tr>
</table>
</div>
</div>
</table>
</body>
var DEBUG=true;
var debugCheckbox;
var hourSlider;
var minSlider;
var secSlider;
var millisSlider;
var alarmSlider;
function debug_setup() {
debugCheckbox = createCheckbox('', false);
debugCheckbox.parent("checkboxDebug")
hourSlider = createSlider(0, 23, 12);
hourSlider.parent("sliderHours")
minSlider = createSlider(0, 59, 0);
minSlider.parent("sliderMinutes")
secSlider = createSlider(0, 59, 0);
secSlider.parent("sliderSeconds")
millisSlider = createSlider(0, 999, 0);
millisSlider.parent("sliderMillis")
alarmCheckbox = createCheckbox('', false);
alarmCheckbox.parent("checkboxAlarm")
alarmSlider = createSlider(0, 60, 0);
alarmSlider.parent("sliderAlarm")
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="clock.js"></script>
<script language="javascript" type="text/javascript" src="runner.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
</table>
</body>
<head>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
<img src="preview.jpg" width="960" height="500"/>
</body>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="clock1.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
</table>
</body>
{
"commits": [
{
"sha": "0f4ec0df94538f7a6dac1254dbf3763e8a10d792",
"name": "final"
},
{
"sha": "f7809979a17703326a259c8e97163e5ccbaa3b10",
"name": "clock_alarm"
},
{
"sha": "ae749e4fedb1082b44c97259c970d5d549e61f7e",
"name": "original_clock"
},
{
"sha": "8c2ddafb299f6ed24b68d12bf9008eb98cdd39e9",
"name": "maeda_clock"
},
{
"sha": "d873871be650e53582894210d2a1240da7b9fa9a",
"name": "sketch"
}
]
}
var canvasWidth = 960;
var canvasHeight = 500;
var prevSec;
var millisRolloverTime;
var nextAlarm;
var debug_is_on = (typeof DEBUG !== 'undefined');
function setup () {
// create the drawing canvas, save the canvas element
var main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
// this is true if debug.js is included
if(debug_is_on) {
debug_setup();
}
turn_off_alarm();
}
function turn_on_alarm() {
nextAlarm = millis() + 20000;
print("Alarm on: T minus 20 seconds");
}
function turn_off_alarm() {
nextAlarm = -1;
print("Alarm turned off");
}
function mouseClicked() {
if (debug_is_on && debugCheckbox.checked()) {
return;
}
if (nextAlarm > 0) {
turn_off_alarm();
}
else {
turn_on_alarm();
}
}
// taking ideas from http://cmuems.com/2016/60212/deliverables/deliverables-02/
function draw () {
var H, M, S, mils, alarm;
if (debug_is_on && debugCheckbox.checked()) {
hourSlider.removeAttribute('disabled');
minSlider.removeAttribute('disabled');
secSlider.removeAttribute('disabled');
millisSlider.removeAttribute('disabled');
alarmCheckbox.removeAttribute('disabled');
alarmSlider.removeAttribute('disabled');
H = hourSlider.value();
M = minSlider.value();
S = secSlider.value();
mils = millisSlider.value();
if (alarmCheckbox.checked()) {
alarm = alarmSlider.value();
}
else {
alarm = -1;
}
}
else {
// Fetch the current time
H = hour();
M = minute();
S = second();
if (nextAlarm > 0) {
now = millis();
var millis_offset = nextAlarm - now;
if (millis_offset < -10000 ){
// turn off alarm
nextAlarm = -1;
alarm = -1;
}
else if (millis_offset < 0) {
alarm = 0;
}
else {
alarm = millis_offset / 1000.0;
}
}
else {
alarm = -1;
}
// Reckon the current millisecond,
// particularly if the second has rolled over.
// Note that this is more correct than using millis()%1000;
if (prevSec != S) {
millisRolloverTime = millis();
}
prevSec = S;
mils = floor(millis() - millisRolloverTime);
if (debug_is_on) {
hourSlider.attribute('disabled','');
minSlider.attribute('disabled','');
secSlider.attribute('disabled','');
millisSlider.attribute('disabled','');
alarmCheckbox.attribute('disabled','');
alarmSlider.attribute('disabled','');
hourSlider.value(H);
minSlider.value(M);
secSlider.value(S);
millisSlider.value(mils);
alarmCheckbox.checked(alarm >= 0);
alarmSlider.value(alarm);
}
}
obj = {};
obj.hours = H;
obj.minutes = M;
obj.seconds = S;
obj.millis = mils;
obj.seconds_until_alarm = alarm;
draw_clock(obj);
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
}
// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 960;
offscreenCanvas.height = 500;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 960, 500);
context.drawImage(this.canvas, 0, 0, 960, 500);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/jpeg');
imageData = imageData.replace('image/jpeg', downloadMime);
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg');
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
if(doZoom) {
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment