我们用Python来做一个天气时钟。也就是既能显示时间,也能显示未来12小时天气。我们的产品设计效果如下图:
一、时钟部分
这个天气时钟首先我们先做时钟部分。
时钟有时针、分针和秒针。这里用来绘制用到了Python Trutle库。以小时针为例。我们先
- 拿起画笔pen.penup()
- 笔移动到表盘中心点pen.goto(global_x_shift, global_y_shift)
- 带上笔的颜色, pen.color(hour_color)
- 设置笔的初始方向 pen.setheading(90)
- 设置笔的顺时针选择角度angle,对于时针来说就是angele=(hour /12)*360+(minute/60)*30
- 然后向右旋转角度pen.rt(angle)
- pen.pendown()放下笔开始绘画
- pen.fd(hour_hand) 向前绘制长度hour_hand。
# draw a clock using the pen i created
def draw_clock(hour, minute, second, pen):
pen.hideturtle()
# Draw the hour han
# 有关Python Turtle常用的操作见http://www.cse.msu.edu/~ldillon/cse-ctl/Spring2015/Meeting07/turtleCheatSheet.pdf
pen.penup() # 暂停绘画,和底下的pendown是一对
pen.goto(global_x_shift, global_y_shift)
pen.color(hour_color)
pen.pensize(6) # 小时针的宽度
pen.setheading(90) # 设置角度,0(east), 90(north), 180(west), 270(south)
angle = (hour / 12) * 360 + (minute/60) * 30 # 根据当前时间,小时针应该便宜的角度
pen.rt(angle) # 向右/顺时针旋转角度,turtle.rt和turtle.right一样
pen.pendown() # 开始绘画,和上面的penup是一对
pen.fd(hour_hand) # 小时针的长度,向前绘制,turtle.fd同turtle.forward
# Draw the minute hand
pen.penup()
pen.goto(global_x_shift, global_y_shift)
pen.color(minute_color)
pen.setheading(90)
angle = (minute / 60.0) * 360 # optional + (s/60) * 6
pen.rt(angle)
pen.pendown()
pen.fd(minute_hand)
# Draw the second hand
pen.penup()
pen.goto(global_x_shift, global_y_shift)
pen.color(second_color)
pen.setheading(90)
angle = (second / 60) * 360
pen.rt(angle)
pen.pendown()
pen.fd(second_hand)
二、未来12小时天气
获取未来12小时天气预报这个update_forecast函数,我们通过拉取openweathermap的接口,得到了温度,体感温度,风速和天气类型图标。
这些天气数值和图标准备好之后。会放在数组待用。
def update_forecast():
global hour_cursor
# weather ID breakdown https://openweathermap.org/weather-conditions
# use https://ezgif.com/maker for gif conversion
logging.debug("---- update_forecast() ----")
hour_cursor = int(time.strftime("%I")) # %I表示12小时制
meridiem = time.strftime('%p') # %p表示上午AM或者下午PM
logging.debug("hour_cursor: " + str(hour_cursor))
for num in range(12):
# current hour
logging.debug("current hour: " + str(hour_cursor) + " " + meridiem)
# forecast hour
logging.debug("forecast hour: " + str(int(hour_cursor)+num))
logging.debug("temperature: " + str(data["hourly"][num]["temp"]))
logging.debug("feels like: " + str(data["hourly"][num]["feels_like"]))
logging.debug("wind speed: " + str(data["hourly"][num]["wind_speed"]))
logging.debug(data["hourly"][num]["weather"][0]["description"])
logging.debug("weather ID: " + str(data["hourly"][num]["weather"][0]["id"]))
logging.debug("POP: " + str(data["hourly"][num]["pop"]))
if 'rain' not in data["hourly"][num]:
logging.debug("no rain data")
else:
logging.debug("rain: " + str(data["hourly"][num]["rain"]))
temp_array[num] = data["hourly"][num]["temp"] # 温度
temp_feel_array[num] = data["hourly"][num]["feels_like"] # 体感温度
wind_array[num] = data["hourly"][num]["wind_speed"] # 风速
id_array[num] = data["hourly"][num]["weather"][0]["id"] # 天气icon id,见https://openweathermap.org/weather-conditions
path_theme = os.path.join(path, theme)
if 232 >= id_array[num] >= 200:
idImage_array[num] = os.path.join(path_theme, "11d@2x.gif")
elif 321 >= id_array[num] >= 300:
idImage_array[num] = os.path.join(path_theme, "09d@2x.gif")
elif 504 >= id_array[num] >= 500:
idImage_array[num] = os.path.join(path_theme, "10d@2x.gif")
elif id_array[num] == 511:
idImage_array[num] = os.path.join(path_theme, "13d@2x.gif")
elif 531 >= id_array[num] >= 520:
idImage_array[num] = os.path.join(path_theme, "09d@2x.gif")
elif 622 >= id_array[num] >= 600:
idImage_array[num] = os.path.join(path_theme, "13d@2x.gif")
elif 781 >= id_array[num] >= 701:
idImage_array[num] = os.path.join(path_theme, "50d@2x.gif")
elif id_array[num] == 800:
idImage_array[num] = os.path.join(path_theme, "01d@2x.gif")
elif id_array[num] == 801:
idImage_array[num] = os.path.join(path_theme, "02d@2x.gif")
elif id_array[num] == 802:
idImage_array[num] = os.path.join(path_theme, "03d@2x.gif")
elif id_array[num] == 803 or id_array[num] == 804:
idImage_array[num] = os.path.join(path_theme, "04d@2x.gif")
else:
logging.error("Invalid weather ID")
logging.debug(temp_array)
logging.debug(id_array)
logging.debug(idImage_array)
for image in idImage_array:
wn.addshape(image) # 画布上画上天气图标
天气icon放置的位置就是原本时钟上的小时数位置。也就是x和y坐标通过公式计算:
hour_x = []
hour_y = []
for i in range(60, -300, -30):
i_r = math.radians(i)
hour_x.append((math.cos(i_r)*radius))
hour_y.append((math.sin(i_r)*radius))
三、总结
完整的程序我放在了这里:weatherClock/weatherClock.py at master · lumanyu/weatherClock (github.com)
本程序通过小时和天气的创新融合,运用程序员的技能做了一个实用工具。