From 3b056d9e855c7cfaca021c2077a0c17d21a0e2a2 Mon Sep 17 00:00:00 2001 From: ArticNet Date: Sat, 4 Apr 2020 03:12:26 +0900 Subject: [PATCH] Added Dot Clock initial release --- apps.json | 13 +++ apps/dotclock/ChangeLog | 1 + apps/dotclock/clock-dot-icon.js | 1 + apps/dotclock/clock-dot.js | 162 ++++++++++++++++++++++++++++++++ apps/dotclock/clock-dot.png | Bin 0 -> 1844 bytes 5 files changed, 177 insertions(+) create mode 100644 apps/dotclock/ChangeLog create mode 100644 apps/dotclock/clock-dot-icon.js create mode 100644 apps/dotclock/clock-dot.js create mode 100644 apps/dotclock/clock-dot.png diff --git a/apps.json b/apps.json index 90194b1c3..5f072c11e 100644 --- a/apps.json +++ b/apps.json @@ -889,5 +889,18 @@ {"name":"barclock.app.js","url":"clock-bar.js"}, {"name":"barclock.img","url":"clock-bar-icon.js","evaluate":true} ] + }, + { "id": "dotclock", + "name": "Dot Clock", + "icon": "clock-dot.png", + "version":"0.01", + "description": "A Minimal Dot Analog Clock", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"dotclock.app.js","url":"clock-dot.js"}, + {"name":"dotclock.img","url":"clock-dot-icon.js","evaluate":true} + ] } ] diff --git a/apps/dotclock/ChangeLog b/apps/dotclock/ChangeLog new file mode 100644 index 000000000..26f95bbde --- /dev/null +++ b/apps/dotclock/ChangeLog @@ -0,0 +1 @@ +0.01: Based on the Analog Clock app, minimal dot interface \ No newline at end of file diff --git a/apps/dotclock/clock-dot-icon.js b/apps/dotclock/clock-dot-icon.js new file mode 100644 index 000000000..62d1dea2a --- /dev/null +++ b/apps/dotclock/clock-dot-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("AH4A/AH4A/AH4AmgkEF/4A/KyxodDpHX66YtF5AA/AH4AobDYbTF94A/AH4A/AG/X64FIAgILEACcEggvIAIQCGAYgfPF+qPUF5QA/AH4AGyAuuAAJf/ABEEggbtF94A/AH4A/bCzqdF96Y/F/4A/AH4A/AGIA==")) \ No newline at end of file diff --git a/apps/dotclock/clock-dot.js b/apps/dotclock/clock-dot.js new file mode 100644 index 000000000..a4b3f260f --- /dev/null +++ b/apps/dotclock/clock-dot.js @@ -0,0 +1,162 @@ +let g; +let Bangle; + +const locale = require('locale'); +const p = Math.PI / 2; +const pRad = Math.PI / 180; +const faceWidth = 100; // watch face radius +let timer = null; +let currentDate = new Date(); +let hourRadius = 60; +let minRadius = 80; +const centerPx = g.getWidth() / 2; + +const seconds = (angle) => { + const a = angle * pRad; + const x = centerPx + Math.sin(a) * faceWidth; + const y = centerPx - Math.cos(a) * faceWidth; + + // if 15 degrees, make hour marker larger + const radius = (angle % 15) ? 2 : 4; + g.fillCircle(x, y, radius); +}; + +const hourDot = (angle,radius) => { + const a = angle * pRad; + const x = centerPx + Math.sin(a) * hourRadius; + const y = centerPx - Math.cos(a) * hourRadius; + g.fillCircle(x, y, radius); +}; + +const minDot = (angle,radius) => { + const a = angle * pRad; + const x = centerPx + Math.sin(a) * minRadius; + const y = centerPx - Math.cos(a) * minRadius; + g.fillCircle(x, y, radius); +}; + +const drawAll = () => { + g.clear(); + currentDate = new Date(); + // draw hands first + onMinute(); + // draw seconds + const currentSec = currentDate.getSeconds(); + // draw all secs + + for (let i = 0; i < 60; i++) { + if (i > currentSec) { + g.setColor(0, 0, 0.6); + } else { + g.setColor(0.3, 0.3, 1); + } + seconds((360 * i) / 60); + } + onSecond(); +}; + +const resetSeconds = () => { + g.setColor(0, 0, 0.6); + for (let i = 0; i < 60; i++) { + seconds((360 * i) / 60); + } +}; + +const drawMin = () => { + g.setColor(0.5, 0.5, 0.5); + for (let i = 0; i < 60; i++) { + minDot((360 * i) / 60,1); + } +}; + +const drawHour = () => { + g.setColor(0.5, 0.5, 0.5); + for (let i = 0; i < 12; i++) { + hourDot((360 * 5 * i) / 60,1); + } +}; + +const onSecond = () => { + g.setColor(0.3, 0.3, 1); + seconds((360 * currentDate.getSeconds()) / 60); + if (currentDate.getSeconds() === 59) { + resetSeconds(); + onMinute(); + } + g.setColor(1, 0.7, 0.2); + currentDate = new Date(); + seconds((360 * currentDate.getSeconds()) / 60); + g.setColor(1, 1, 1); +}; + +const drawDate = () => { + g.reset(); + g.setColor(1, 1, 1); + g.setFont('6x8', 2); + + const dayString = locale.dow(currentDate, true); + // pad left date + const dateString = ((currentDate.getDate() < 10) ? '0' : '') + currentDate.getDate().toString(); + const dateDisplay = `${dayString} ${dateString}`; + // console.log(`${dayString}|${dateString}`); + // center date + const l = (g.getWidth() - g.stringWidth(dateDisplay)) / 2; + const t = centerPx - 6 ; + g.drawString(dateDisplay, l, t); + // console.log(l, t); +}; +const onMinute = () => { + if (currentDate.getHours() === 0 && currentDate.getMinutes() === 0) { + g.clear(); + resetSeconds(); + } + // clear existing hands + g.setColor(0, 0, 0); + hourDot((360 * currentDate.getHours()) / 12,4); + minDot((360 * currentDate.getMinutes()) / 60,3); + + // Hour + drawHour(); + // Minute + drawMin(); + + // get new date, then draw new hands + currentDate = new Date(); + g.setColor(1, 0, 0); + // Hour + hourDot((360 * currentDate.getHours()) / 12,4); + g.setColor(1, 0.9, 0.9); + // Minute + minDot((360 * currentDate.getMinutes()) / 60,3); + if (currentDate.getHours() >= 0 && currentDate.getMinutes() === 0) { + Bangle.buzz(); + } + drawDate(); +}; + +const startTimers = () => { + timer = setInterval(onSecond, 1000); +}; + +Bangle.on('lcdPower', (on) => { + if (on) { + // g.clear(); + drawAll(); + startTimers(); + Bangle.drawWidgets(); + } else { + if (timer) { + clearInterval(timer); + } + } +}); + +g.clear(); +resetSeconds(); +startTimers(); +drawAll(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); diff --git a/apps/dotclock/clock-dot.png b/apps/dotclock/clock-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..702ac90655f0a552c6567174ddba0330134694ef GIT binary patch literal 1844 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@HXQ2>tmIipR1RclAn~S zSCLx)lxJYDv9BmdOwLX%QAkQn&&;z`dcS+Wl0s&Rtx~wDuYqrYb81GWM^#a3aFt(3 za#eP+Wr~u$9hXgo70`g()RIJnirk#MVyg;UC9t_xKsHENUr7P1q$Jx`DZ)2E!8yMu zRl!uxRL?-kj!VI&C?(A*$i)q+8OXC$$|xx*u+rBrFE7_CH`dE9O4m2Ew6xSWFw!?N z(gmu}Ew0QfNvzP#D^>;>0WrfRwK%ybv!En1KTiQQ?NYIsRz8p8Cv zVyO3l0ih3)(KpmH&_`CDT9JuEIY!B| zRX}D%YEFbpW^QU;G0;@FD-e>AI3%6(bMlLVfyp}6R>=@-7d#%Uz;eF%DL^S>G$~JK z=YXR8w9Fi!Tyc=QlY*zKvzei#nVGJU9>f@6q*(#=W~NoTB$fbG85tNE=o**+QHX(& zm8pf5fr++(rIi81gJ9LbypWPul1NBBC`BvS0Co8KT6ts^m*f{!f`uT-JUF!w!h>*g zGQsIvK>-}gR*A`=P`6boD9TSMO-@Y#dkbhBM7B6Tt)x7$DAh3?7{Rtmj%jI`!1$?D z2mqyA1r6WCA_ZeZ1&~iPQ8kulqyi1a?L~d41NA`}59UG}eGEU?fE6I+RG>bH7_bBY z7A5-dvINM1mqw|1z#^y!Sk{ysSzpG$z}S=tj2(Z zSm^Xl&UEYUHp-l`WTsKfw)b@_bNAKmkM~@6s?@c!JD&X?)4EfUno6qb?CFmV{rXjt zyH)kKP3^q%uPg1(KfnCBMs9=aCNIDB-yQYxGad$9u$7N3u#Q`C+>g82BDrf_-?=kB zftT&xuiX4-?e$fmzwhk7HpSx=*A-K)evMUW9R3{sYb945wLbLLOKqBfo$$M>Pnr&u zPm|OCxccZzq59}Gu7{EnvPH|5ueOLg>g9Ht^YrPDPd2Ug`e}E~d)DNiJ0m+|AI*Ky z!YO#C=1oj48v|)d6 ztL5|RF0uQq-MTL-LXxB2gm3D;9i&-d-8xNU%iV_JjaN2*vQy_5xH)0{uC~3kFD8Co zw^UwzL;6YAzxrQ+wFYN_M`SSr1Gg{;GcwGYBLNhg>gnPb64CnhMj%&%0#8HYTfVtV zf7`dYzZ7`wIN`*m7-OS$wXd)(4`&ft((kXUd~L*&ehb4$yno}Jj)(J`ZC)5o1H z9|YT;zN_=$Qob-Nd`)NUq3U|G$+u2?o8^A$s?xjZWoOxU7l!_czp`-8cKLIAW{dEg zS)4ZYV)9JSn?Bx)WnaB~7r^=6`M~L_U)zq0{#(E(8_78NgXirnGoJB)DmzbCKbLh* G2~7Zz)0$-f literal 0 HcmV?d00001