S5G3 用 GGB 作动态时钟
本周的学用数学要来玩转时钟。作出可随时间转动的时钟,并可调整转速,观察数字时钟与指针时钟。在技巧上最主要是练习序列来绘制时钟,并且用滑动杆的脚步来同步控制滑动杆。
但我觉得最可贵的还是呈现形式与问题拆解思维。要根据教学需求构想画面要有哪些交互元素,接着再去拆解要达到这个效果需要分解成哪些步骤。

你将学会
用【序列】来绘制时间版面刻度
用数学思维来将时间对应指针的位置描述出来
用【滑动杆脚本】来同步滑动杆
使用【按钮】来启动、暂停动画
【系统时间】的使用
先备概念:
序列
弧度与角度的关系
按钮脚本的初步认识
操作方法
2 如何绘制钟面的刻度线?

问:如何绘制钟面的刻度线?
答:利用【序列】先建钟面上 60 个的点列 mPs 来定位。接着利用 mPs 往内缩 0.95 倍来绘制分针刻度线 mSs。 再缩为 0.9 倍来绘制时针刻度线 hSs ,但对于 hSs 则是用 5 作为间隔。
cR = 5
O =(0,0)
cO = 圆周(O,cR)
mPs = 序列((cR;pi/2-pi/30*k),k,1,60)
mSs = 序列(线段(mPs(k),0.95*mPs(k)),k,1,60)
hSs=序列(线段(mPs(k),0.9*mPs(k)),k,5,60,5)
问:如何将数字放到合适的位置?
答:最基本的想法,是用时针刻度的位置*0.8。但这个定位点不是文字的正中央。因此,再加入些偏移量,例如 (-0.3,-0.3) 。但对于 10,11,12 这些二位数的位置平移量可以再大一些,就再利用 floor(k/10) 来微调。
hTs=序列(文本(k,0.8*mPs(5k)),k,1,12) #初版
hTs=序列(文本(k,0.8*mPs(5k)-(0.3,0.3)),k,1,12) #第二版
hTs=序列(文本(k,0.8*mPs(5k)-0.1*(3+floor(k/10),3)),k,1,12) #第三版
3 如何绘制钟面上的指针?

问:如何让指针指到正确位置?
答:主要先决定秒针的转角。对秒针而言,s秒的转动量为 s/60*2π,而时针转动的方向与数学角度的算法不同。因此, sA 为 pi/2-s/60*2*pi。
但对分针来说,就还需要考虑 m 与 s 的影响,3600 秒绕一圈。所以先将 m分s秒换为 60*m+s ,接着以 (m*60+s)/(60*60)*2*pi 来计算其位置。
对于时针,要考虑 h,m,s 的影响,用 12*60*60 秒为一圈来计算出其位置。
# 先设定时分秒的滑动条 h m s
h = 滑动条(0,24,1)
m = 滑动条(0,60,1)
s = 滑动条(0,60,1)
# 设定指针的半径
hR = 2
mR = 3
sR = 4
# 设定转角 sA, mA, hA,再用向量 vector 来绘制指针
sA = pi/2-s/60*2*pi
vS = 向量(O,O+(sR; sA))
mA = pi/2-(m*60+s)/(60*60)*2*pi
vM = 向量(O,O+(mR; mA))
hA = pi/2-(h*60*60+m*60+s)/(12*60*60)*2*pi
vH = 向量(O,O+(hR; hA))
4 设定时间动画

问:如何让时间稳定的转动?
答:在用 h m s 滑动杆再控制时针时,无法处理分针绕一圈,时针前进一大格的问题。这时用另个时间滑动杆 t 来显示一天经过的秒数,再将这数值通过整除与取余数来调整 h,m,s 的数值。
问:如何控制转速模拟真实的时间。
答:因为,滑动杆移动一次为 10s ,而 t 的范围为一天的 86400秒。因此,将 t 的移动速度设定为 v/8640,通过调整速度v,可达到真实时间加快为 v 倍的效果。
v = 滑动条(1,120,1)
t = 滑动条(0,24*60*60,1)
t = 滑动条(0,24*60*60,1,v/(86400))
# 加入速度设定
#以下对滑动条设定对 h,m, s 的连动
赋值(s,取余(t,60))
赋值(m,取余(floor(t/60),60))
赋值(h,取余(floor(t/(60*60)),24))
5 启动与暂停按钮

问:是否可让 h, m, s 拉到底端时,自动回到原位,同时做到进位的效果?
答:在 t,m,s 的脚本同时取更新 t 的值。再由 t 的值来修正 s,m,h。
补充:这个写法有个缺点就是 s,m,h 无法变小,只能增大。
# 秒针滑动条的脚本
赋值(t,取余(t+1,86400))
赋值(s,取余(t,60))
赋值(m,取余(floor(t/60),60))
赋值(h,取余(floor(t/3600),24))
# 分针滑动条的脚本
赋值(t,取余(t+60,86400))
赋值(s,取余(t,60))
赋值(m,取余(floor(t/60),60))
赋值(h,取余(floor(t/3600),24))
# 时针滑动条的脚本
赋值(t,取余(t+3600,86400))
赋值(s,取余(t,60))
赋值(m,取余(floor(t/60),60))
赋值(h,取余(floor(t/3600),24))
问:如何用按钮来设定自动转动与停止。
答:用【启动动画】指令。停止与启动都是这个指令,差别在于参数的 True与 False。
#启动脚本
启动动画(t,True)
#停止脚本
启动动画(t,False)
启动动画(h,False)
启动动画(m,False)
启动动画(s,False)
6 系统时间

问:是否可让时间显示现在的时间呢?
答:可利用【系统时间】,这会取得一串list {毫秒、秒、分、时、日、月、年、月(文)、星期(文)、星期}。再通过 ( ) 来取得对应的秒、分、时的数值。
ST=系统时间()
赋值(t,ST(4)*3600+ST(3)*60+ST(2))

问:如何显示数字时间?
答:先用 floor(h/10) 取得 h 的十位数字,再用 Mod(h,10) 取得 h 的个位数字。 对于m, s 的取法也是类似。
floor(h / 10)取余(h, 10):floor(m / 10)取余(m, 10):floor(s / 10)取余(s, 10)
相关链接
【GGB】https://www.geogebra.org/m/e8cdcgdh
【Bili 】https://www.bilibili.com/video/bv1sz411B7s1
【YouTube】 https://www.youtube.com/playlist?list=PLXH05kw-i_5IADW91fs6CZ7XxrVLGB5OR