作者 | Ryoko
來源 | 凹凸數據
七夕(各種節日、紀念日)又到啦,程式設計師(怎麼會不是單身呢)又要想招來哄女友啦?想必大家都知道各種各樣的代碼式浪漫。
想必大家都知道各種各樣的代碼式浪漫,比如定製的二維碼,讓女友掃碼後進入一個定製的H5 頁面,那麼這個頁面里可以放的內容是——
回憶,是經典的選項。該如何呈現回憶呢?
不難想到可以用 js 來實現各種動畫效果,直接 copy 各種庫組合組合是不錯,但親力親為還是需要經過精心設計,操作起來有一定的難度。
這裡給大家提供一個簡單的點子,用 Python 來製作酷炫的動態條形圖,展示你們在一起的歷程吧!
例子如下:
動態條形圖
首先,不妨猜想一下這個是如何實現的。動畫即是一幀一幀靜態畫面的連續播放,所以我們只需要將每一天都畫一次圖,再拼成 GIF 即可。
如下為第一天和最後一天的條形圖:
再來看一下用於畫圖的每日數據,假設2020年1月1日為起始日期,1月20日為當天(即發布供檢閱的)日期,故要對這些數據畫20次圖(別怕,兄dei)。
進入代碼環節:先按需求讀取數據(讀表最愛的 pandas 庫又出現啦)。為了便於處理日期,將 excel 中的日期一列的值轉為字符串格式,再利用 datatime 將起始日期設為時間戳格式。
import pandas as pd
import 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 plt
import matplotlib.animation as ani
import pandas as pd
import 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,我也…大概是限制的網段沒覆蓋到吧哈哈)
(嗯?我在公司划水的事情暴露了嗎)。
不過在那之前,先把本地的 html 寫好吧!
通過開頭的最終(不是最終的)效果圖可以發現,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 里讓它們顯示出來:
<body>
<div class="process_gif" id="process"></div>
<div class="show_txt" id="content_1"></div>
</body>
編寫 js 腳本實現列印功能,在頁面加載時就調用列印函數 typing,並且在動態圖播放到最後一幅時,將其替換成靜態圖:
<script type="text/javascript">
/// 顯示文字功能 ----------------------------------
let divTyping = document.getElementById('content_1'); //通過id獲取div節點
let a = 0;
timer = 0;
str = "我們已經相遇 20 天<br>告白後過了 13 天<br>First Kiss 至今 5 天";
function 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); # 單位是毫秒,根據動態圖的時長來設置
}
</script>
來看一下,真的是真的.真.最終效果圖:
注意:動圖的時長和幀數,以及動圖在html中與逐行列印文字同步顯示,大家還需根據實際內容對代碼進行調整,以達到最佳效果哦!
好了不想寫了,快速部署的部分大家自己搜索資料吧......
部署站點到github
言歸正傳,Html 頁面中更多的花樣還有待各位發揮了,現在到最後環節——把頁面 duang 上 Github。
先註冊登錄最大同性交友網站 Github(到底有幾個最大同性交友…)的過程略過,創建一個新的倉庫,用於存放 html 文件和圖片。
創建後得到一個倉庫地址。
準備上傳我們的站點文件。
上傳文件還需要先安裝 git(安裝地址:https://git-scm.com/downloads/),之後在安裝目錄下打開 git-bash.exe。
1、進入站點目錄($ 符號後為輸入的命令):
2、在該目錄生成 git 管理:
3、輸入 add * 添加目錄下所有的文件,也可指定文件名或文件夾,添加文件夾的格式為 add dirname/ :
4、輸入 git status 查看是否將所需文件添加進了緩衝區:
5、輸入提交版本的注釋(引號內為注釋內容):
6、將本地倉庫管理關聯至 github(剛才得到的倉庫地址):
7、上傳文件:
最後一步上傳時會相繼彈出 Github 帳號密碼輸入框,輸入後即可等待上傳完成。
完成後回到 Github,發現幾個文件已經躺在倉庫里了,再點擊 Settings:
在 Gitub Pages 一欄中選擇 master branch:
現在,你的站點可以通過這個連結來訪問啦,把它丟進二維碼里就大功告成了!可以用手機掃碼看一下demo。
圖1
這個經常抽風,下面將帶大家部署到企鵝雲。
事情往往不像看上去那樣簡單,儘管我們已經歷盡重重步驟,但依然遺留了兩個坑:gif 圖片在頁面中加載慢(通過工具壓縮圖片大小來解決),部分瀏覽器不支持 window.onload (優化 js 腳本)。
本文不再多贅述,大家自己去探索吧(咔咔)!另外,可以加的東西還有詞雲、動態字符畫、抽獎轉盤等等,如果各位有什麼其它有趣的玩意兒可以加進頁面中,還請給筆者提供更多點子!
部署站點到企鵝雲
最近發現 Github 有點抽風,之前部署的站點無法訪問了!於是回家把站點遷到了企鵝雲,果然國內伺服器響應體驗更佳,而且操作十分簡便,讓我們來看看怎麼做吧。
首先進入企鵝雲官網,在左上角的欄目中找到「對象儲存」,進入頁面後點擊「立即使用」。
然後創建一個桶子,記得選「公有讀私有寫」,完全私有就不能通過外部訪問啦。
把相關文件丟到桶子裡。
返回桶子列表,在剛才創建的桶子右側點擊「配置管理」,開啟靜態網站後就可以通過訪問節點的連結瀏覽站點了,是不是感覺比 Github page 快多了,哈哈。
再來掃掃試試吧!~