mirror of https://github.com/espruino/BangleApps
Merge branch 'master' of github.com:espruino/BangleApps
commit
55d7a893b1
|
@ -0,0 +1 @@
|
|||
0.01: First rev. Could use a little optimization love.
|
|
@ -0,0 +1,11 @@
|
|||
# Rings watchface
|
||||
|
||||
Ring based watchface, read from the outside in. When the watch is unlocked the circles shrink to show the date ring.
|
||||
|
||||
By Amos Blanton, inspired by and remixed from Rinkulainen by Jukio Kallio.
|
||||
|
||||

|
||||
View when watch is locked.
|
||||
|
||||

|
||||
Watch unlocked, showing the date.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+CR0GAokMiUMAQQLFAooAYg0SjEYjwAHjA0BGLQXChgrEGIIGCG4wyBLbItFFQYnDFgYREGIRiRCISHIFQgEDMYgCCSoYuPhi1IXg4vFMYI5CSh4uBJwYAEj5bDAAjGCjIzDTwguWFoMShkOgIVFgMOLQMYHwYCDGBZdKiUHisckcOwNWgGBxEkikjkcWhCmBj4sBMJ67GDIMAiojBAANd1lWq2BAAMOo4LCjkBiQWBLwQ0CK4RfGFw0SgJbBAAc51mBles1lPhwMENoMMGAJgDj0MGAoEBBgYuDhAgFkeIFgOBAQN6F40jisGYgQADRpguJL4LtEgE4B48VMIRiDSIxeFjEBDo1HWQMAqgACGIKdFAAUPYYUSSIjsJgAdHh1O1HSAAmovEICY8Id4RTDMAK9GRoMVDIscgGo6YuFAAPT1FOitHCosGFoYpBdwZeFg4uRGIYwHh4sBYIsAS4ZeJFwItKGAiSFjjyBL4aQBdo0MCwlHhxdMYgkAYJApDF48OIotOFw2ov1+NA3TvyRFisYMAJXDgCOEjCOEo8VLwuoqjXCAAIxF1EIJQsSF4RbBhkMXxcO5giEFwMqAAQwBqhkB6ZABqkdYArsBdQUSF4q+FkdUWQwrCAAQFFvzxGg5eCeARfGCYkdF4t+FI0Aq1VleBwNWgAvFFAgvHL4ovOq2swIvB1msgFAF7yPHlesLYNWwIHBR5AvJiUWd4ovE6S6EAQJfB1gyDF4rvCAAcSgwvEjEVCYdHh+o6ZgFAAksq1WlcrGwMHJQkciUfF4kAGwsOCgt4F4jCCqgABv1+SwcBgBKEkcVjAvEhkAjA0DAAIUEkcI1AvFAA+oHAIZGh0YAAQqBFAMSFodWkhFFjlOMAwAH6d+DA0MjESGIYrD1kAwOswMyIwsVGBouBhAXGXwRfCLYYsBAQIDBvUcC4lHGALzFFojHBFw0jcwq+CL4eBgGs1lWgwYFo8cgF+5gpBAAQvB0SlBo4VFh5bBRwIuBRwMGL4QABleBrgHBhxKGPYMIql+AAVUg8VjouGi0Mj7uELwYAGhkZhjZFMQTeCAAYIDdgqNCFoMMLwoABlYFBmJsCj8GGA4yCAAQMIFwJaCdoZeIBwQACj8Mh4jIABUWFwS8Dj0SLwovIGAMShCEBAB8PQ4JbCLoSNBABIwHjEGh4xMjkVDQMZRggEBFxQwIDIUMhEVdQQrDFgMOg0SCIQYFRY4wPj4gBiUMg8MAQS0BCgINBLYguDGBxJCGI4kCA5S7GFxwABa4QAXiQrPAAQ/CSZAANjBaQGA8MGKUYhiLSGJEGcgIsMfQItYGIxlChg0BAAUSFYYtQ"))
|
|
@ -0,0 +1,210 @@
|
|||
// Rings watch face
|
||||
// for Bangle.js 2
|
||||
// by Amos Blanton
|
||||
// Remixed from / inspired by Rinkulainen watch face by Jukio Kallio
|
||||
|
||||
// To Do:
|
||||
// Make Month / year text buffer 1/2 size
|
||||
// Optimize text positioning transforms
|
||||
|
||||
const watch = {
|
||||
x:0, y:0, w:0, h:0,
|
||||
color:"#000000",
|
||||
dateRing : { size:109, weight:20, color:"#00FF00", cursor:14, numbers: true },
|
||||
hourRing : { size:85, weight:20, color:"#00FFFF", cursor:14, numbers: true },
|
||||
minuteRing : { size:61, weight:20, color:"#FFFF00", cursor:14, numbers: true },
|
||||
screen : { width:g.getWidth(), height:g.getHeight(), centerX: g.getWidth() *0.5, centerY: g.getHeight() * 0.5, cursor: 14, font:"6x8:2" },
|
||||
};
|
||||
|
||||
const month= ["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY",
|
||||
"AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"];
|
||||
|
||||
var wait = 60000; // wait time, normally a minute
|
||||
// timeout used to update every minute
|
||||
var drawTimeout;
|
||||
// Global for use in shrink / unshrink animations
|
||||
var counter = 1;
|
||||
|
||||
// Buffer for month circle text, 1/2 screen size (will be scaled up)
|
||||
var monthCircleTextBuffer= Graphics.createArrayBuffer(watch.screen.width,watch.screen.height,1,{msb:true});
|
||||
var monthCircleTextImg = monthCircleTextBuffer.asImage();
|
||||
monthCircleTextImg.transparent = 1;
|
||||
var lastMonthCircleImageText = "";
|
||||
|
||||
// Calculate number of days in this month / year for date ring
|
||||
const getDays = (year, thisMonth) => {
|
||||
return new Date(year, thisMonth, 0).getDate(); // getMonth() Jan = 0.
|
||||
};
|
||||
|
||||
// Schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
draw();
|
||||
}, wait - (Date.now() % wait));
|
||||
}
|
||||
|
||||
// Draws a time circle (date, hours, minutes)
|
||||
function drawTimeCircle(color, size, weight, range, value ) {
|
||||
// variables for vertex transformations and positioning time
|
||||
var tver, tobj, tran;
|
||||
var ttime = (value / range) * (Math.PI * 2);
|
||||
|
||||
// draw circle and line
|
||||
g.setColor(color).fillCircle(watch.screen.centerX, watch.screen.centerY, size);
|
||||
g.setColor("#000000").fillCircle(watch.screen.centerX, watch.screen.centerY, size - weight);
|
||||
|
||||
tver = [-watch.screen.cursor, 0, watch.screen.cursor, 0, watch.screen.cursor, -size*1.01, -watch.screen.cursor, -size*1.05];
|
||||
|
||||
tobj = { x:watch.screen.centerX, y:watch.screen.centerY, scale:1, rotate:ttime };
|
||||
tran = g.transformVertices(tver, tobj);
|
||||
g.fillPoly(tran);
|
||||
|
||||
// Draw numbers
|
||||
g.setFontAlign(0,0).setFont(watch.screen.font, 2).setColor(1,1,1);
|
||||
|
||||
// size - 21 is the right offset to get the numbers aligned in the circle.
|
||||
tver = [-1, 0, 1, 0, 1, -size, -1, -(size -21)];
|
||||
tran = g.transformVertices(tver, tobj);
|
||||
g.setColor(1,1,1);
|
||||
g.drawString(value, (tran[4]+tran[6]) / 2 , (tran[5]+tran[7]) / 2 );
|
||||
|
||||
}
|
||||
|
||||
// Draws text for month and year in date circle
|
||||
function drawMonthCircleText( text, circleSize, range, value){
|
||||
|
||||
// If the text isn't the same as last time, write it into a graphic object.
|
||||
if(text != lastMonthCircleImageText){
|
||||
|
||||
monthCircleTextBuffer.clear();
|
||||
monthCircleTextBuffer.fillRect(0,0,watch.screen.width,watch.screen.height);
|
||||
|
||||
var tver, tobj, tran;
|
||||
|
||||
// From here: https://forum.espruino.com/comments/16781795/
|
||||
var gr = Graphics.createArrayBuffer(24,16,1,{msb:true});
|
||||
var grimg = gr.asImage();
|
||||
grimg.transparent = 1;
|
||||
monthCircleTextBuffer.setColor(0,0,0);
|
||||
|
||||
for(z=0; z < text.length; z++){
|
||||
tobj = { x:watch.screen.centerX, y:watch.screen.centerY, scale:1, rotate: ((z + 1) / range) * (Math.PI * 2) };
|
||||
tver = [-1, 0, 1, 0, 1, -circleSize, -1, -(circleSize -21)];
|
||||
tran = monthCircleTextBuffer.transformVertices(tver, tobj);
|
||||
gr.clear().setColor(1,1,1).fillRect(0,0,24,16).setColor(0,0,0).setFont(watch.screen.font).setFontAlign(0,0).drawString(text[z],12,8);
|
||||
|
||||
monthCircleTextBuffer.drawImage(grimg,
|
||||
(tran[4]+tran[6]) / 2,
|
||||
(tran[5]+tran[7]) / 2,
|
||||
{rotate:((z+1) / range) * (Math.PI * 2) });
|
||||
}
|
||||
|
||||
lastMonthCircleImageText = text;
|
||||
}
|
||||
|
||||
// Determine correct rotation for text in ring ( opposite the date position )
|
||||
var offset = value + (range / 2) - (text.length / 2);
|
||||
if(offset > range)
|
||||
offset = offset - range;
|
||||
var rotation = (offset / range) * (Math.PI * 2);
|
||||
|
||||
// Draw the image of text to the screen at that rotation
|
||||
g.drawImage(monthCircleTextImg, watch.screen.centerX, watch.screen.centerY, {scale:1, rotate:rotation });
|
||||
|
||||
}
|
||||
|
||||
// Animate by shrinking or expanding circles
|
||||
function shrinkCircles(toggle){
|
||||
// If there's a queued draw operation,removeit so animation isn't interrupted.
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
|
||||
var date = new Date();
|
||||
var delta = 1;
|
||||
|
||||
if(counter > 12)
|
||||
{
|
||||
counter = 1;
|
||||
// We're finished, so queue next draw.
|
||||
queueDraw();
|
||||
return;
|
||||
}
|
||||
|
||||
if(toggle) // We are shrinking
|
||||
delta = counter * 2 * -1;
|
||||
else // We are expanding
|
||||
delta = counter *2 - 24;
|
||||
|
||||
// Clear space on screen.
|
||||
g.setColor(watch.color);
|
||||
g.fillRect(0, 0, watch.screen.width, watch.screen.height);
|
||||
|
||||
// Draw the date ring (unless it's the last run of an expansion).
|
||||
if(counter < 11 || toggle){
|
||||
drawTimeCircle(watch.dateRing.color, watch.dateRing.size + delta, watch.dateRing.weight, getDays(date.getFullYear(), date.getMonth()+1), date.getDate() );
|
||||
// Draw month and year in date ring
|
||||
drawMonthCircleText( month[date.getMonth()]+" "+date.getFullYear(), watch.dateRing.size - 24, getDays(date.getFullYear(), date.getMonth()+1), date.getDate()) ;
|
||||
}
|
||||
|
||||
drawTimeCircle(watch.hourRing.color, watch.hourRing.size + delta, watch.hourRing.weight, 12, date.getHours() );
|
||||
|
||||
drawTimeCircle(watch.minuteRing.color, watch.minuteRing.size + delta, watch.minuteRing.weight, 60, date.getMinutes() );
|
||||
|
||||
counter += 1;
|
||||
setTimeout(shrinkCircles, 10, toggle);
|
||||
}
|
||||
|
||||
|
||||
// main draw function
|
||||
function draw() {
|
||||
// make date object
|
||||
var date = new Date();
|
||||
var unLockedOffset = 0;
|
||||
|
||||
// Reset the state of the graphics library
|
||||
g.reset();
|
||||
|
||||
// Clear the area where we want to draw the time
|
||||
g.setColor(watch.color);
|
||||
g.fillRect(0, 0, watch.screen.width, watch.screen.height);
|
||||
|
||||
// If unlocked, draw date ring and text and make hour and minute rings smaller
|
||||
if(!Bangle.isLocked()){
|
||||
unLockedOffset = 24;
|
||||
drawTimeCircle(watch.dateRing.color, watch.dateRing.size - unLockedOffset, watch.dateRing.weight, getDays(date.getFullYear(), date.getMonth()+1), date.getDate() );
|
||||
drawMonthCircleText( month[date.getMonth()]+" "+date.getFullYear(), watch.dateRing.size - unLockedOffset, getDays(date.getFullYear(), date.getMonth()+1), date.getDate()) ;
|
||||
}
|
||||
|
||||
drawTimeCircle(watch.hourRing.color, watch.hourRing.size - unLockedOffset, watch.hourRing.weight, 12, date.getHours() );
|
||||
drawTimeCircle(watch.minuteRing.color, watch.minuteRing.size -unLockedOffset , watch.minuteRing.weight, 60, date.getMinutes() );
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
// Trigger shrink / expand animation on unlock / lock events
|
||||
Bangle.on('lock', on=>{
|
||||
if (on) { // locked, expand circles
|
||||
counter = 1;
|
||||
shrinkCircles(false);
|
||||
} else
|
||||
{ // unlocked, shrink circles and show date ring
|
||||
counter = 1;
|
||||
shrinkCircles(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// End function definitions / start of initial execution.
|
||||
|
||||
// Clear the screen once, at startup
|
||||
g.clear();
|
||||
|
||||
// draw immediately at first
|
||||
draw();
|
||||
|
||||
|
||||
// console.log("Whatevs");
|
||||
|
||||
// Show launcher when middle button pressed
|
||||
Bangle.setUI("clock");
|
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,16 @@
|
|||
{ "id": "rings",
|
||||
"name": "Rings - an animated watchface",
|
||||
"shortName":"Rings",
|
||||
"version":"0.01",
|
||||
"description": "Ring based watchface that animates to show the date when unlocked. Inspired by / remixed from Rinkulainen.",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot1.png"}, {"url":"screenshot2.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"rings.app.js","url":"app.js"},
|
||||
{"name":"rings.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Loading…
Reference in New Issue