Better code needed for hands on watchface

Former Member
Former Member
Hi,

I'm having trouble making sharp, readable hands on a watchface.
Can anyone send me a better version, maybe with polygons if that is better. I really cannot get the hang of polygons as I don't understand the command.
Or perhaps steer me in the right direction ?
Thank you in advance

I've been using this code :

// Define variables
var center_x;
var center_y;
var minute_radius;
var hour_radius;
var seconds_radius;
var TWO_PI = Math.PI * 2;
var ANGLE_ADJUST = Math.PI / 2.0;
var showSeconds=false;
var now = Time.now();
var clockTime = Sys.getClockTime();
var hour = clockTime.hour;
var minute = clockTime.min;
var seconds = clockTime.sec;
var hour_fraction = minute / 60.0;
var minute_angle = hour_fraction * TWO_PI;
var seconds_angle = seconds * TWO_PI / 60.0;
var hour_angle = (((hour % 12) / 12.0) + (hour_fraction / 12.0)) * TWO_PI;
seconds_angle -= ANGLE_ADJUST;
minute_angle -= ANGLE_ADJUST;
hour_angle -= ANGLE_ADJUST;

// draw the hour hand
dc.setPenWidth(9); hour_radius = 60;
dc.setColor(Gfx.COLOR_YELLOW,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + hour_radius * Math.cos(hour_angle)),
(center_y + hour_radius * Math.sin(hour_angle)));
dc.setPenWidth(5); hour_radius = 59;
dc.setColor(Gfx.COLOR_BLACK,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + hour_radius * Math.cos(hour_angle)),
(center_y + hour_radius * Math.sin(hour_angle)));
dc.setPenWidth(3); hour_radius = 50;
dc.setColor(Gfx.COLOR_WHITE,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + hour_radius * Math.cos(hour_angle)),
(center_y + hour_radius * Math.sin(hour_angle)));

// draw the minute hand
dc.setPenWidth(9); minute_radius = 95;
dc.setColor(Gfx.COLOR_YELLOW,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + minute_radius * Math.cos(minute_angle)),
(center_y + minute_radius * Math.sin(minute_angle)));
dc.setPenWidth(5); minute_radius = 94;
dc.setColor(Gfx.COLOR_BLACK,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + minute_radius * Math.cos(minute_angle)),
(center_y + minute_radius * Math.sin(minute_angle)));
dc.setPenWidth(3); minute_radius = 85;
dc.setColor(Gfx.COLOR_WHITE,Gfx.COLOR_BLACK);
dc.drawLine(center_x, center_y,
(center_x + minute_radius * Math.cos(minute_angle)),
(center_y + minute_radius * Math.sin(minute_angle)));

if (showSeconds) {
// draw the seconds hand
dc.setPenWidth(3); seconds_radius = 95;
dc.setColor(Gfx.COLOR_YELLOW,Gfx.COLOR_TRANSPARENT);
dc.drawLine(center_x, center_y,
(center_x + seconds_radius * Math.cos(seconds_angle)),
(center_y + seconds_radius * Math.sin(seconds_angle)));
dc.drawCircle((center_x + seconds_radius * Math.cos(seconds_angle)),
(center_y + seconds_radius * Math.sin(seconds_angle)),2);}
  • Fractional seems to work at least in the simulator where I tried (probably fenix6 or fr955). It doesn't round it, cause you can see the difference in a few pixels as you add/subtract let's say 0.25.

    For rectangles I think (again, at least in the simulator) there are certain devices that seem to behave differently (and I only draw rectangles with horizontal, vertical sides, not some strange angle) in terms of 2 things:

    1. The pixel in the corner

    2. In some cases (maybe it is the parity of the dimension as you said) the "other" side is 1 pixel off (I don't see what could explain this, as in my case I only used Numbers, I'm never between whole numbers) I started to add a constant 0 or 1 per device to fix this, but then I gave up, as I can't know if something looks bad on the simulator and I fix it it would fix it on the real device or rather screw it - that's one trigger to this idea: forums.garmin.com/.../ciq-device-information-app-and-database-in-github

  • I think they get rounded up / down. I don't recall the exact number but adding 0.5 to it was enough for it to be rounded up to the expected x value in this case.

    Yeah, in my experience, when you pass a float to some drawing function which deals with pixel coordinates or dimensions, then the value is truncated (rounded towards zero), as if toNumber() was called on the value.

    Fractional pixels don’t really make sense unless they’re handled via blending. While I maybe can see that happening on the newer devices with a gpu, I’m almost 100% sure it wouldn’t work on an older device. 

  • But drawCircle does use fractional calculation, because if it would do what you suggest (more or less toNumber() on the input) then it would only "jump" 1 pixel when you increase / decrease the input by 1. But if you add/dec 0.25, 0.50, 0.75 you'll see that the rendered circle is slightly different. Easiest to see when you try to draw a circle on the screen size.

  • Maybe it’s changed since I last looked at it. In the thread I linked (from several years ago), you can see how bad it looks when you try to draw a full screen circle, and you can see where a Garmin employee agrees the only way to get around it is to draw four overlapping circles.

    If they have fixed it since then, that’s great, but again I doubt it would be fixed on older watches, especially those without a GPU (and built-in blending / anti-aliasing.)