• Edit 2: solved the problem. I am unaware of the ethics of this forum. Should I indicate my error and let the post to potentially help someone in the future, or simply remove it?

    Edit: Kept only a more minimal version of the code, that still bugs, and got rid of what worked.

    Hello, as a first project, I have made my own watch face, and it is working great except for a tiny detail.
    The program's logic should be as follows :

    • a function to update the clock face every minute is defined, then it is executed with :

      id = setInterval(updateClock, 0);
    • The clock should update every minute on time, therefore the interval is modified inside updateClock :

      seconds = new Date().getSeconds(),
      changeInterval(id, (60 - seconds) * 1000);
    • Inside this same function, all complications are drawn :
      a rectangle holding the battery percentage at the top right
      a big HH:MM in the middle of the screen
      a smaller DD MMM YYYY
      and on the bottom a L M [M] J V S D (that's monday, tuesday, etc in french) with the current day inside a square

    Everything works exactly as desired except on the very first update after uploading : the battery percentage (line 30) and the square around the day of the week (line 31) are not drawn as desired. As soon as the next minute begins, everything is drawn perfectly and stays that way.

    Here is the whole code :

    var id,
        bottomOffset = 13,
        topOffset = 31,
        weekString = "L M M J V S D";
    function padToTwoDigits(s) {
      return s < 10 ? "0" + s : s;
    function frenchDayOfWeek(d) {
      return (d - 1) % 7; // convert from S M T W T F S to L M M J V S D
    function updateClock() {
      let battery = padToTwoDigits(E.getBattery()) + "%",
          W = g.getWidth(),
          H = g.getHeight(),
          date = new Date(),
          seconds = date.getSeconds(),
          day = frenchDayOfWeek(date.getDay()),
          baseXOffset = (W - g.stringWidth(weekString)) / 2,
          stringLeftOffset = g.stringWidth(weekString.substring(0, 2 * day)),
          xLeft = baseXOffset + stringLeftOffset - 1,
          stringRightOffset = g.stringWidth(weekString.substring(0, 2 * day + 1)),
          xRight = baseXOffset + stringRightOffset;
        .setFont("Vector", 20)
        .drawString(battery, W - 20, 15)
        .drawRect(xLeft, H - bottomOffset, xRight, H - topOffset);
      changeInterval(id, (60 - seconds) * 1000);
    id = setInterval(updateClock, 0);

    Should anyone have a hint, I would be most thankful :)

    2 Attachments

    • wrong.png
    • correct.png
  • maybe setTimeout is better fit? setInterval is supposed to be used when the method passed to it is called repeatedly in regular intervals, does not make much sense with value of 0 or when changing it all the time.

  • Glad you got it fixed! ideally, yes, if you could just put a note about what was wrong that'd be much better than deleting the thread, and hopefully it'll help someone else!

    I'm not sure if it's related to your issue, but what I do notice is you do g.clear(1) which resets the state of graphics back to defaults (which is great), but before you do that you use g.stringWidth which will give you the width of the string in the current font (which could be anything).

    So I'd move g.clear(1) to the start of the function...

    Also, most clocks generally use the form used in https://www.espruino.com/Bangle.js+Clock­+Font to ensure the clock face is always drawn on the minute:

    // timeout used to update every minute
    var drawTimeout;
    // schedule a draw for the next minute
    function queueDraw() {
      if (drawTimeout) clearTimeout(drawTimeout);
      drawTimeout = setTimeout(function() {
        drawTimeout = undefined;
      }, 60000 - (Date.now() % 60000));
  • That was the problem, so I won't even edit my post to indicate what it was :)
    Thank you for the helpful pointers!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Bangle.js 2 setInterval() / changeInterval() problem

Posted by Avatar for pouzzler @pouzzler