Last active
January 8, 2022 21:51
-
-
Save lelandbatey/7ca16176ed74d3e5ecdc63dd732390b4 to your computer and use it in GitHub Desktop.
Color clock - represent the hands of a clock as the "color edges" of a pie chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> | |
<!--<script src="timemachine.js"></script>--> | |
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment-with-locales.min.js"></script>--> | |
<body style="margin: 0;"> | |
<canvas id='canvas' width='1000' height='1000'></canvas> | |
</body> | |
<script> | |
// timemachine.config({ | |
// // dateString: '5. May 2018, 04:21:47 PDT', | |
// dateString: '5. May 2018, 05:27:14 PDT', | |
// tick: true | |
// }); | |
function mod(lhs, n) { | |
return ((lhs%n)+n)%n; | |
}; | |
// let _COLORS_ = ['red', 'green', 'blue', 'pink', 'grey']; | |
let _COLORS_ = ['#550800', '#50A162', '#012C34', '#D49E6A', '#801F15', '#106022', '#0F444F', '#804915', '#D4746A', '#00400E', '#437983', '#552900']; | |
function getColorsBy60(num) { | |
num = Math.floor(num); | |
let idx = mod(num, 60) % (_COLORS_.length-1); | |
let second = (idx+1) % (_COLORS_.length-1); | |
// console.log(idx, second); | |
return [_COLORS_[idx], _COLORS_[second]]; | |
} | |
function roundTo(n, digits) { | |
if (digits === undefined) { | |
digits = 0; | |
} | |
var multiplicator = Math.pow(10, digits); | |
n = parseFloat((n * multiplicator).toFixed(11)); | |
return Math.round(n) / multiplicator; | |
} | |
/* | |
// The mysterious constants in the below getClockHandsCrossBin are merely odd | |
// ways of formatting the original fractions calculated in the mathematica | |
// stackexchange linked below. The following code can be used as an example to | |
// convert those fractions into times-past-midnight when the hands cross, which is | |
// the format actually use in the code: | |
function fractions_to_timestamps() { | |
var print = console.log; | |
function zeropad(x, pad, chr) { | |
return String(x).padStart(pad, chr); | |
} | |
var times = [0, 720 / 11, 1440 / 11, 2160 / 11, 2880 / 11, 3600 / 11, 4320 / 11, 5040 / 11, 5760 / 11, 6480 / 11, 7200 / 11]; | |
let first = times[1]; | |
function fmttime(first) { | |
//print(`first: ${first}`); | |
//print(`first % 1: ${first % 1}`); | |
//print(`first | 0: ${first | 0}`); | |
let minutes = first | 0; // Only the minutes post midnight | |
let minfrac = first % 1; // The remaining fraction of a minute | |
//print(`minutes / 60: ${minutes / 60}`); | |
//print(`minfrac * 60: ${minfrac * 60}`); | |
let hoursafter = (minutes / 60) | 0; // Hours after midnight when this crossover occurs | |
let mininhour = (minutes % 60); // Minutes remaining in hour when crossover happens | |
let secinmin = (minfrac * 60) | 0; | |
let msinsec = (((minfrac * 60) % 1) * 1000) | 0; | |
//print(`hoursafter : ${hoursafter}`); | |
//print(`mininhour: ${mininhour}`); | |
//print(`secinmin: ${secinmin}`); | |
//print(`msinsec: ${msinsec}`); | |
var tp = (x) => zeropad(x, 2, '0'); | |
let nicerep = `${hoursafter}:${tp(mininhour)}:${tp(secinmin)}.${zeropad(msinsec, 3, 0)}`; | |
print(nicerep); | |
} | |
for (var i = 0; i < times.length; i++) { | |
fmttime(times[i]); | |
} | |
} | |
fractions_to_timestamps(); | |
*/ | |
function getClockHandsCrossBin() { | |
// The times that the hour and minutes hands cross. Originally found here: | |
// https://mathematica.stackexchange.com/a/582 | |
// | |
// [0, 720/11, 1440/11, 2160/11, 2880/11, 3600/11, 4320/11, 5040/11, 5760/11, 6480/11, 7200/11] | |
// ['00:00:00', '01:05:27', '02:10:54', '03:16:21', '04:21:49', '05:27:16', '06:32:43', '07:38:10', '08:43:38', '09:49:05', '10:54:32'] | |
let crossing_hours = [0, 10527.2727, 21054.5454, 31621.8181, 42149.0909, 52716.3636, 63243.6363, 73810.909, 84338.1818, 94905.4545, 105432.7272]; | |
// Format the current moment in these terms | |
let now = new Date(); | |
let hour = now.getHours() % 12; | |
let minute = String(now.getMinutes()).padStart(2, '0'); | |
let second = String(now.getSeconds()).padStart(2, '0'); | |
let milliseconds = String(now.getMilliseconds()).padStart(3, '0'); | |
let str = `${hour}${minute}${second}.${milliseconds}`; | |
let curtime = parseFloat(str, 10); | |
let bin = 0; | |
for (var i = 0; i < crossing_hours.length; i++) { | |
if (crossing_hours[i] <= curtime) { | |
bin = i; | |
} | |
} | |
// if (roundTo(curtime, 1) === 42149.9 ) { | |
// debugger; | |
// } | |
// console.log(str, bin); | |
return bin; | |
} | |
/// Moment returns a number representing the number of milliseconds that have passed since the epoch | |
/// time (1970). | |
function nowtime() { | |
return Date.now(); | |
} | |
function minute_of_hour() { | |
return ((nowtime()/1000) % 3600) / 60; | |
} | |
function hour_of_day() { | |
return ((nowtime()/1000) % (24 * 60 * 60)) / (24 * 60 * 60); | |
} | |
function sleep(ms) { | |
return new Promise((resolve) => setTimeout(resolve, ms)) | |
} | |
$(document).ready(() => { | |
var canv = document.getElementById('canvas'); | |
canv.height = $(window).height(); | |
canv.width = $(window).width(); | |
var context = canv.getContext('2d'); | |
context.fillStyle = 'black'; | |
context.fillRect(0, 0, canv.width, canv.height); | |
let sx = canv.width/2; | |
let sy = canv.height/2; | |
let circle_rad = 2*Math.PI; | |
let twelve_oclock = 0.75 * circle_rad; | |
function draw_pie_slice(origin, radius, start_angle, end_angle) { | |
let [sx, sy] = origin; | |
context.beginPath(); | |
context.moveTo(sx, sy); | |
context.arc(sx, sy, radius, start_angle, end_angle); | |
context.lineTo(sx, sy); | |
context.fill(); | |
} | |
function get_12hour_progress(relative_start) { | |
if (typeof relative_start === "undefined") { | |
relative_start = twelve_oclock; | |
} | |
let halfday_ms = (12 * 60 * 60 * 1000); | |
// Instead of getting moment, we're going to hack together a different way to get the current time in the local time zone | |
let now = new Date(); | |
let now_ms = now.getMilliseconds(); | |
let now_seconds = now.getSeconds() * 1000; | |
let now_minutes = now.getMinutes() * 60 * 1000; | |
let now_hours = (now.getHours() % 12) * 60 * 60 * 1000; | |
let now_cumulative_ms = now_ms + now_seconds + now_minutes + now_hours; | |
let halfday_progress = (now_cumulative_ms % halfday_ms) / halfday_ms; | |
let hdnp = (circle_rad * halfday_progress) + relative_start; | |
return hdnp % circle_rad; | |
} | |
function get_hour_progress(relative_start) { | |
if (typeof relative_start === "undefined") { | |
relative_start = twelve_oclock; | |
} | |
let hour_progress = (nowtime() % 3600000) / 3600000; | |
let hnp = (circle_rad*hour_progress) + relative_start; | |
let hour_rad_progress = hnp % circle_rad; | |
return hour_rad_progress; | |
} | |
function get_minute_progress(relative_start) { | |
let minute_progress = (nowtime() % 60000) / 60000; | |
let mnp = (circle_rad*minute_progress) + relative_start; | |
return mnp % circle_rad; | |
} | |
function do_the_frame() { | |
// let [bg, fg] = getColorsBy60(hour_of_day()% 12); | |
let [bg, fg] = getColorsBy60(getClockHandsCrossBin()); | |
// console.log(bg, fg); | |
context.fillStyle = 'lightgrey'; | |
context.fillRect(0, 0, canv.width, canv.height); | |
let clock_radius = sy*0.9; | |
// Get our "progress" through the 12-hour block | |
let halfday_rad_progress = get_12hour_progress(); | |
// Get our "progress" through the current hour | |
let hour_rad_progress = get_hour_progress(); | |
// Get our "progress" through the current minute | |
// let minute_rad_progress = get_minute_progress(hour_rad_progress); | |
// console.log(halfday_rad_progress, hour_rad_progress, Date.now(), bg, fg); | |
// if (hour_rad_progress < halfday_rad_progress && halfday_rad_progress - hour_rad_progress < 0.05) { | |
// context.fillStyle = fg; | |
// } else { | |
// context.fillStyle = bg; | |
// } | |
context.fillStyle = bg; | |
// Draw the background circle | |
context.beginPath(); | |
context.arc(sx, sy, clock_radius, twelve_oclock, twelve_oclock+circle_rad); | |
context.fill(); | |
context.beginPath(); | |
context.fillStyle = fg; | |
draw_pie_slice([sx, sy], clock_radius, halfday_rad_progress, hour_rad_progress); | |
window.requestAnimationFrame(do_the_frame); | |
} | |
do_the_frame(); | |
}); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment