
Bangle.js Clock Faces
We'll assume you've already been through the Bangle.js Development page and have an idea how to get started.
If so you're now connected and can write some simple code - let's have a go at making a clock!
To do this, it's best to use the right-hand side of the IDE - once uploaded you can tweak values and call functions using the REPL on the left if you want to.
Drawing the time
Copy the following code to the right of the IDE and click Upload ():
function draw() {
// work out how to display the current time
var d = new Date();
var h = d.getHours(), m = d.getMinutes();
var time = h + ":" + m.toString().padStart(2,0);
// Reset the state of the graphics library
g.reset();
// Clear the area where we want to draw the time
g.clearRect(50,50,100,120);
// draw the current time
g.drawString(time, 50, 50);
}
// Clear the screen once, at startup
g.clear();
// draw immediately at first
draw();
// now draw every second
var secondInterval = setInterval(draw, 1000);
You'll now have some tiny text in the middle of the screen, which displays the time.
The slightly odd m.toString().padStart(2,0)
code zero-pads the minutes for us (so 1 minute past 12 gets written as "12:01"
rather than "12:1"
).
Why is the code formatted like this? Check out the Code Style page for some tips and the reasoning behind it.
Changing font
First, we'll want to make the text bigger, and properly centered. You have a bunch of options here which you can see on the Fonts page.
We're going to load a custom font for 7 segments called Font7x11Numeric7Seg
,
which can then be used with g.setFont("7x11Numeric7Seg")
.
// Load fonts
require("Font7x11Numeric7Seg").add(Graphics);
// position on screen
const X = 160, Y = 140;
function draw() {
// work out how to display the current time
var d = new Date();
var h = d.getHours(), m = d.getMinutes();
var time = (" "+h).substr(-2) + ":" + m.toString().padStart(2,0);
// Reset the state of the graphics library
g.reset();
// draw the current time (4x size 7 segment)
g.setFont("7x11Numeric7Seg",4);
g.setFontAlign(1,1); // align right bottom
g.drawString(time, X, Y, true /*clear background*/);
// draw the seconds (2x size 7 segment)
g.setFont("7x11Numeric7Seg",2);
g.drawString(("0"+d.getSeconds()).substr(-2), X+30, Y, true /*clear background*/);
}
// Clear the screen once, at startup
g.clear();
// draw immediately at first
draw();
// now draw every second
var secondInterval = setInterval(draw, 1000);
Note: To avoid flicker here we're using the 4th argument to drawString
,
which clears the background (by default only the text itself is drawn).
Finally, let's add the date. For this, we can use the locale
library
which means that the data will be in the correct language for each user.
Just add the following at the bottom of the draw
function:
// draw the date, in a normal font
g.setFont("6x8");
g.setFontAlign(0,1); // align center bottom
// pad the date - this clears the background if the date were to change length
var dateStr = " "+require("locale").date(d)+" ";
g.drawString(dateStr, g.getWidth()/2, Y+15, true /*clear background*/);
Extra Clock Features
We now have something that tells the time, but we need to add a few extra bits before we can make this a clock face:
BTN2 to start the launcher
Every clock needs to be able to start the launcher, and the default for this is the middle button. All you need to do is add this to the end of the clock code (not in a function):
// Show launcher when middle button pressed
Bangle.setUI("clock");
Note: In Bangle.js firmwares before 2v08, apps used the following code to
explicitly show the launcher when BTN2
is pressed:
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
. Using
Bangle.setUI
allows users
to install different apps which start the launcher (or other apps) with different
functionality, independent of the clock face.
Widgets
Most clocks show widgets. To do this you just need to add the following code to the end of the clock:
Bangle.loadWidgets();
Bangle.drawWidgets();
You can call Bangle.drawWidgets()
every time the screen is cleared
and widgets need to redraw themselves - but it's good practice to
do that as rarely as possible to avoid flicker.
In our example we only clear the screen once (at startup) so that's
the only time we call Bangle.drawWidgets()
Power saving 1
Right now, we're redrawing the whole screen every second, and this can eat up a reasonable amount of battery (it'll reduce Bangle.js 2 battery life by a factor of 2 or more) compared to updates once a minute.
- If your clock face doesn't show seconds, consider only updating once a minute - here is an example
- If possible, you could update the clock face once a minute using the code above and then update just the area of the clock face responsible for seconds once a second.
Power saving 2
On Bangle.js 1, the screen isn't on all the time, so we can stop updates
when it is off. To do this we listen for the lcdPower
event
and cancel our secondInterval
interval, then restart it when the
screen is turned on (and immediately redraw):
Note: On Bangle.js 2 the screen is on all the time, so this code
isn't required. However you can still use Bangle.on('lock'
to allow
you to display a clock face with seconds only when the Bangle is unlocked.
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
if (secondInterval) clearInterval(secondInterval);
secondInterval = undefined;
if (on) {
secondInterval = setInterval(draw, 1000);
draw(); // draw immediately
}
});
Finally
Your code should now look like this:
// Load fonts
require("Font7x11Numeric7Seg").add(Graphics);
// position on screen
const X = 160, Y = 140;
function draw() {
// work out how to display the current time
var d = new Date();
var h = d.getHours(), m = d.getMinutes();
var time = (" "+h).substr(-2) + ":" + m.toString().padStart(2,0);
// Reset the state of the graphics library
g.reset();
// draw the current time (4x size 7 segment)
g.setFont("7x11Numeric7Seg",4);
g.setFontAlign(1,1); // align right bottom
g.drawString(time, X, Y, true /*clear background*/);
// draw the seconds (2x size 7 segment)
g.setFont("7x11Numeric7Seg",2);
g.drawString(("0"+d.getSeconds()).substr(-2), X+30, Y, true /*clear background*/);
// draw the date, in a normal font
g.setFont("6x8");
g.setFontAlign(0,1); // align center bottom
// pad the date - this clears the background if the date were to change length
var dateStr = " "+require("locale").date(d)+" ";
g.drawString(dateStr, g.getWidth()/2, Y+15, true /*clear background*/);
}
// Clear the screen once, at startup
g.clear();
// draw immediately at first
draw();
// now draw every second
var secondInterval = setInterval(draw, 1000);
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
if (secondInterval) clearInterval(secondInterval);
secondInterval = undefined;
if (on) {
secondInterval = setInterval(draw, 1000);
draw(); // draw immediately
}
});
/* Show launcher when middle button pressed
This should be done *before* Bangle.loadWidgets so that
widgets know if they're being loaded into a clock app or not */
Bangle.setUI("clock");
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
Making an App
Now we have this, we need to turn it into an app for the watch. To do that we need two basic files on the watch:
- The app's code in a JS file
- A JSON
info
file describing the app (name/etc) for the launcher.
First, come up with a unique ID for your app. Don't use spaces, use lowercase letters, and try and make it reasonably short (under 10 characters is a good idea).
It shouldn't already be listed in https://github.com/espruino/BangleApps/tree/master/apps so that it doesn't interfere with other apps you might install.
App Code: myclock.app.js
We'll use myclock
. Now, click the down-arrow below the Upload button,
then choose Storage
, then New File
, and then type myclock.app.js
and click Ok
.
Now, click the Upload
button. The app will be uploaded to the watch
and then executed from the file. With this set, you can easily
continue to develop your app as it is on the watch.
App Info: myclock.app.info
Now we have the app, but it won't appear in the launcher because there is no app info file. To fix this, just copy and paste the following into the left-hand side of the IDE.
It'll write the relevant info to the file myclock.info
require("Storage").write("myclock.info",{
"id":"myclock",
"name":"My Clock",
"type":"clock",
"src":"myclock.app.js"
});
If you now long-press BTN3 to get to the clock, the press
BTN2 to get to the menu, you can scroll down and see My Clock
.
If you select it, it'll execute your app!
You can also go into Settings, and choose it as the default clock
under Select Clock
.
Note: The Bangle App Loader automatically generated this file - we're just doing it here so you can create an app without requiring the loader.
Next Steps
Ok, so now we've got a clock!
- How about adding it to the Bangle.js App Loader? Check out Adding an app to the Bangle.js App Loader
- You can add useful information to the clock face with Clock Info
- You can make the clock Fast Load into the Launcher
- What about auto-hiding the widgets
This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.