七夕(各种节日、纪念日)又到啦,程序员(怎么会不是单身呢)又要想招来哄女友啦?想必大家都知道各种各样的代码式浪漫。 想必大家都知道各种各样的代码式浪漫,比如定制的二维码,让女友扫码后进入一个定制的H5 页面,那么这个页面里可以放的内容是—— 不难想到可以用 js 来实现各种动画效果,直接 copy 各种库组合组合是不错,但亲力亲为还是需要经过精心设计,操作起来有一定的难度。 这里给大家提供一个简单的点子,用 Python 来制作酷炫的动态条形图,展示你们在一起的历程吧! 01
动态条形图 首先,不妨猜想一下这个是如何实现的。动画即是一帧一帧静态画面的连续播放,所以我们只需要将每一天都画一次图,再拼成 GIF 即可。 再来看一下用于画图的每日数据,假设2020年1月1日为起始日期,1月20日为当天(即发布供检阅的)日期,故要对这些数据画20次图(别怕,兄dei)。
进入代码环节:先按需求读取数据(读表最爱的 pandas 库又出现啦)。为了便于处理日期,将 excel 中的日期一列的值转为字符串格式,再利用 datatime 将起始日期设为时间戳格式。 import pandas as pdimport datetime df = pd.read_excel("数据.xlsx" ) df['日期文本' ] = df['日期' ].apply(lambda x: str(x)[:10 ]) t = datetime.datetime(2020 ,1 ,1 ) # 起始日期 选择 matplotlib 库进行绘图:先设置画布,返回模型和画图对象。接着不要忘记设置字体以避免中文显示异常。因为有3个项目需要区分上色,因此再创建一个颜色列表,可以自行百度喜欢的颜色代码。 import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(10 ,6 )) # 画布 plt.rcParams['font.sans-serif' ] = ['Microsoft YaHei'
] # 字体设为微软雅黑 colors = ['#ADD8E6' , '#DC143C' , '#FFC0CB' ] # 颜色列表 编写绘图函数:传入的参数是对于起始日期所经过的天数通过 t + datetime.timedelta(days=date) 计算需要绘制的指定天数的日期,再利用 strftime("%Y-%m-%d") 将其还原为日期文本,然后通过该日期文本取出当天的数据存入新的 df_ 中。下一步即为通过 barh 方法绘制条形图,且每次画新图前需清空上一次的图像。 def draw(date): # 数据处理 ------ current_date = (t + datetime.timedelta(days=date)).strftime("%Y-%m-%d" ) df_ = df[df['日期文本' ].eq(current_date) ] days = df_ ['天数' ] item = df_ ["项目" ] # 绘制条形图 ------ ax.clear() # 重绘 # for i in range(1,len(itme.uni)) ax.barh(item, days, color = colors) 如此之后,调用 draw(19) 来画出经过19天后,也就是第20天的图像,通过 plt.show() 临时查看一下。 和最终效果图还有一定的差距,多了坐标轴标签,少了系列标签、数据标注和右上角的滚动时间。继续完善 draw 函数:
for y, (x,name) in enumerate(zip(days.values,item.values)): # 系列标注 ax.text (x, y, "%s" % x, size=12 ) if x > 1 : ax.text (x-0.5 , y, name, size=14 , ha = 'right') ax.text (1 , 1.01 , current_date, transform = ax.transAxes, size= 20 , ha='right') # 滚动时间 ax.get_xaxis().set_visible(False ) # 隐藏坐标轴 ax.get_yaxis().set_visible(False ) 接下来就是用 for 循环画出20张图并通过 plt.savefig('xxx.png') 一一保存,再使用 imageio 库或其他图像工具来合成 gif 啦! (不不不,慢着慢着)如果真要这样做就太麻烦了,下面该祭出这次的主角了! import matplotlib.animation as ani
matplotlib 库提供了动态绘图的模块,可以帮助我们更加轻松的制作 gif。只需传入模型、绘图函数、和一个 int 类型的列表即可,因此最初设计 draw 函数时所需的参数是天数 date。interval 参数为绘制每张图的时间间隔,用于在 plt.show() 中检查效果。最终保存 gif 图像时可以通过 fps 参数设置帧数。 timeSlot = [x for x in range(0,20)] # 时间轴 animator = ani.FuncAnimation(fig, draw, frames=timeSlot ,interval = 100) animator.save('test.gif',fps=10) import matplotlib.pyplot as pltimport matplotlib.animation as aniimport pandas as pdimport datetime df = pd.read_excel("数据.xlsx" ) df['日期文本' ] = df['日期' ].apply(lambda x: str(x)[:10 ]) t = datetime.datetime(2020 ,1 ,1 ) # 起始日期 fig, ax = plt.subplots(figsize=(10 ,6
)) # 画布 plt.rcParams['font.sans-serif' ] = ['Microsoft YaHei' ] # 字体设为微软雅黑 timeSlot = [x for x in range(0 ,20 )] # 时间轴 colors = ['#ADD8E6' , '#DC143C' , '#FFC0CB' ] # 颜色列表 def draw (date) : print(date) # 数据处理 ------ current_date = (t + datetime.timedelta(days=date)).strftime("%Y-%m-%d" ) df_ = df[df['日期文本' ].eq(current_date)] days = df_['天数' ] item = df_["项目" ] # 绘制条形图 ------ ax.clear() # 重绘 ax.barh(item, days, color = colors) for y, (x,name) in enumerate(zip(days.values,item.values)): # 系列标注 ax.text(x, y, "%s" % x, size=12 ) if x > 1 :
ax.text(x-0.5 , y, name, size=14 , ha = 'right' ) ax.text(1 , 1.01 , current_date, transform = ax.transAxes, size= 20 , ha='right' ) # 滚动时间 ax.get_xaxis().set_visible(False ) # 隐藏坐标轴 ax.get_yaxis().set_visible(False )# draw(19) # plt.savefig('test.png') animator = ani.FuncAnimation(fig, draw, frames=timeSlot ,interval = 100 ) # interval时间间隔 plt.show()# animator.save('test.gif',fps=10) 定制二维码 from MyQR import myqr # 需先安装MyQR库
def QR_myqr () : myqr.run( 'https://' , # 二维码指向链接,或无格式文本(但不支持中文) version = 5 , # 大小1~40 level='H' , # 纠错级别 picture = 'img.jpg' , # 底图路径 colorized = True , # 彩色 contrast = 1.0 , # 对比度 brightness = 1.0 , # 亮度 save_name = 'save.jpg' , # 保存文件名 save_dir = 'D:/' #保存目录 )编写静态html页面 如果需要通过二维码来访问你的网站,那就需要先将其部署到服务器,方法也是多种多样的,比如某企鹅云,个人用户有6个月的免费时常。我们在这里要介绍的是 Github(其实是因为我公司的电脑不能上外网,测试的时候用不了企鹅云才用的 Github,国内手机访问还是放在国内的服务器比较快,大概是的)。
(嗯?就算你问上不了外网却能上 Github,我也…大概是限制的网段没覆盖到吧哈哈) 通过开头的最终(不是最终的)效果图可以发现,Gif 是首尾相接循环播放的,那最后一天的图像一下子闪过去就看不清楚了,可以修改一下传入的时间序列,把最后一幅图再画多几遍,就有停留的效果了。为了更好地展现效果,下面的图中所用数据的时间周期改为了从6月1日到8月25日(七夕),经过了86天,并增加了两条项目。 timeSlot = [x for x in range(0,86)]+[85]*15 直接放进 html 页面里,就单单一张图好像还缺了点什么,那就跟随动图的节奏在下方打印文字吧。首先设置两个 div 的样式,一个用于展示 gif,一个用于打印文字: <head > <style > .process_gif { /*显示动态barh*/ background-image :url ("./process.gif" ); background-repeat : no-repeat; background-size : cover; margin :0 auto;
width : 370px ; height : 220px ; position : relative; z-index : 1 ; } .show_txt { /*显示文字*/ margin :0 auto; background-color : azure; width : 370px ; height : 200px ; position : relative; text-align : center; padding-top : 10px ; z-index : 1 ; }style > head ><body >
<div class ="process_gif" id ="process" >div > <div class ="show_txt" id ="content_1" >div > body >编写 js 脚本实现打印功能,在页面加载时就调用打印函数 typing,并且在动态图播放到最后一幅时,将其替换成静态图:
() { if (a <= str.length) { # 从第一个字开始逐个打印 divTyping.innerHTML = str.slice(0 , a++) + '_' ; timer = setTimeout(typing, 50 ); # 设置打印时间间隔 } else { divTyping.innerHTML = str; //结束打字,移除 _ 光标 clearTimeout(timer); } } window.onload=function () { typing(); setTimeout(function () { thisdiv = document.getElementById("process" ); thisdiv.style.backgroundImage = "url('./process_stop.png')" ; # 将div背景图替换 },2000 ); # 单位是毫秒,根据动态图的时长来设置 } 注意:动图的时长和帧数,以及动图在html中与逐行打印文字同步显示,大家还需根据实际内容对代码进行调整,以达到最佳效果哦! 好了不想写了,快速部署的部分大家自己搜索资料吧...... 04
部署站点到github 言归正传,Html 页面中更多的花样还有待各位发挥了,现在到最后环节——把页面 duang 上 Github。 先注册登录最大同性交友网站 Github(到底有几个最大同性交友…)的过程略过,创建一个新的仓库,用于存放 html 文件和图片。 上传文件还需要先安装 git(安装地址:https://git-scm.com/downloads/),之后在安装目录下打开 git-bash.exe。 3、输入 add * 添加目录下所有的文件,也可指定文件名或文件夹,添加文件夹的格式为 add dirname/ : 4、输入 git status 查看是否将所需文件添加进了缓冲区:
6、将本地仓库管理关联至 github(刚才得到的仓库地址): 最后一步上传时会相继弹出 Github 账号密码输入框,输入后即可等待上传完成。 完成后回到 Github,发现几个文件已经躺在仓库里了,再点击 Settings: 在 Gitub Pages 一栏中选择 master branch: 现在,你的站点可以通过这个链接来访问啦,把它丢进二维码里就大功告成了!可以用手机扫码看一下demo。
事情往往不像看上去那样简单,尽管我们已经历尽重重步骤,但依然遗留了两个坑:gif 图片在页面中加载慢(通过工具压缩图片大小来解决),部分浏览器不支持 window.onload (优化 js 脚本)。 本文不再多赘述,大家自己去探索吧(咔咔)!另外,可以加的东西还有词云、动态字符画、抽奖转盘等等,如果各位有什么其它有趣的玩意儿可以加进页面中,还请给笔者提供更多点子! 部署站点到企鹅云 最近发现 Github 有点抽风,之前部署的站点无法访问了!于是回家把站点迁到了企鹅云,果然国内服务器响应体验更佳,而且操作十分简便,让我们来看看怎么做吧。 首先进入企鹅云官网,在左上角的栏目中找到“对象储存”,进入页面后点击“立即使用”。 然后创建一个桶子,记得选“公有读私有写”,完全私有就不能通过外部访问啦。 返回桶子列表,在刚才创建的桶子右侧点击“配置管理”,开启静态网站后就可以通过访问节点的链接浏览站点了,是不是感觉比 Github page 快多了,哈哈。