Found 2 analog clock sample codes in this forum, but both using translate() and rotate() functions which make the line looks jiggy and a bit pixelated. At least on my iPad 1. So here I offer another way to draw analog clock using simple trigonometry so the hour hands look smooth. Here’s the code…
abs = math.abs
sin = math.sin
cos = math.cos
rad = math.rad
function circle(x,y,r)
ellipseMode(RADIUS)
ellipse(x,y,r,r)
end
function getLocalDateTime()
datetime = os.date("*t")
return datetime
end
function clock12ToDeg(clockVal)
if clockVal >= 12 then clockVal = clockVal-12 end
degVal = 90 - (30 * clockVal)
return degVal
end
function clock60ToDeg(clockVal)
if clockVal >= 60 then clockVal = clockVal-60 end
degVal = 90 - (6 * clockVal)
return degVal
end
function degToClock(degree, r,x,y)
if x == nil then x = clockX end
if y == nil then y = clockY end
if r == nil then r = clockR end
-- get position of a clock hand's degree
mx = x + r * cos(rad(degree))
my = y + r * sin(rad(degree))
return mx, my
end
function clockMode(sweep)
if sweep then
if last_sec == second then
sweepStep = sweepStep + 1
else
maxStep = sweepStep + 1
sweepStep = 0
last_sec = second
end
else
sweepStep = 0
end
end
function drawNumbers()
textMode(CENTER)
font("AmericanTypewriter-CondensedBold")
fontSize(digitSize)
local w,h = textSize('0')
-- adjust text position to clock size
local r = clockR - clockR/10 - borderThick
local x = clockX
local y = clockY
-- draw 12 clock numbers
for i = 5, 55, 5 do
local x,y = degToClock(clock60ToDeg(i),r,x,y)
text(i/5,x,y)
end
text('12', degToClock(clock60ToDeg(0),r,x,y))
end
function drawDial()
-- draw clock border
fill(backColor)
stroke(borderColor)
strokeWidth(borderThick)
circle(clockX, clockY, clockR + borderThick/2 + clockR/10)
-- draw clock dot marks
fill(clockColor)
stroke(backColor)
noStroke()
local dx,dy
for i = 0, 59 do
dx,dy = degToClock(clock60ToDeg(i))
if i % 5 ~= 0 then
circle(dx,dy,clockR/100) -- small tick
else
circle(dx,dy,2.5*clockR/100) -- big tick
end
end
drawNumbers()
end
function drawHour(hourVal)
local r = clockR*2/3 - borderThick
strokeWidth(hourThick)
stroke(hourColor)
line(clockX, clockY, degToClock(clock12ToDeg(hourVal),r))
end
function drawMinute(minuteVal)
local r = clockR - borderThick*2
strokeWidth(minuteThick)
stroke(minuteColor)
line(clockX, clockY, degToClock(clock60ToDeg(minuteVal),r))
end
function drawSecond(secondVal)
-- movement mode
if isSweep then
secondVal = secondVal + sweepStep/maxStep
end
-- hand
local r = clockR
strokeWidth(secondThick)
stroke(secondColor)
line(clockX, clockY, degToClock(clock60ToDeg(secondVal),r))
-- tail
local r = clockR/5
strokeWidth(secondThick*2)
line(clockX, clockY, degToClock(clock60ToDeg(secondVal+30),r))
-- center
fill(secondColor)
circle(clockX, clockY, secondThick*3)
end
function adjustSize()
borderThick = clockR/30
hourThick = clockR/10
minuteThick = clockR/15
secondThick = clockR/30
digitSize = clockR/5
end
function setup()
-- clock size
clockX = WIDTH/2
clockY = HEIGHT/2
clockR = 200 --play with this value to see it auto-adjust
adjustSize()
-- clock mode setup
isSweep = true
maxStep = 30
sweepStep = 0
last_sec = getLocalDateTime().sec
iparameter("quartz",0,1,0)
-- clock color
backColor = color(192,192,192,255)
clockColor = color( 0, 0, 0,255)
borderColor = color(255,255,255,255)
hourColor = color( 0, 0,192,255)
minuteColor = color( 0, 0,128,255)
secondColor = color(192, 0, 0,255)
-- param and watch
iparameter("clockR",50,300,clockR)
--watch("second")
iparameter("add_minute",-30,30,0)
iparameter("add_hour",-12,12,0)
--watch("maxStep")
end
function draw()
background(0)
smooth()
adjustSize()
-- get local time
datetime = getLocalDateTime()
second = datetime.sec
minute = datetime.min + add_minute
hour = datetime.hour + add_hour
-- set clock mode
isSweep = (quartz == 0)
clockMode(isSweep)
-- draw clock
drawDial()
drawHour(hour + minute/60)
drawMinute(minute + second/60)
drawSecond(second)
end
Any suggestions are welcome. Hope this code will be useful. Thank you.