七夕快到了,作為一個程式設計師,怎麼可能不給女朋友一個驚喜呢
一、動態條形圖
首先,不妨猜想一下這個是如何實現的。動畫即是一幀一幀靜態畫面的連續播放,所以我們只需要將每一天都畫一次圖,再拼成 GIF 即可。
如下為第一天和最後一天的條形圖:
再來看一下用於畫圖的每日資料,假設2020年1月1日為起始日期,1月20日為當天(即釋出供檢閱的)日期,故要對這些資料畫20次圖(別怕,兄dei)。
進入程式碼環節:先按需求讀取資料(讀表最愛的 pandas 庫又出現啦)。為了便於處理日期,將 excel 中的日期一列的值轉為字串格式,再利用 datatime 將起始日期設為時間戳格式。
importpandasaspd
importdatetime
df=pd.read_excel("資料.xlsx")
df['日期文字']=df['日期'].apply(lambdax:str(x)[:10])
t=datetime.datetime(2020,1,1)#起始日期
選擇 matplotlib 庫進行繪圖:先設定畫布,返回模型和畫圖物件。接著不要忘記設定字型以避免中文顯示異常。因為有3個專案需要區分上色,因此再建立一個顏色列表,可以自行百度喜歡的顏色程式碼。
importmatplotlib.pyplotasplt
fig,ax=plt.subplots(figsize=(10,6))#畫布
plt.rcParams['font.sans-serif']=['MicrosoftYaHei']#字型設為微軟雅黑
colors=['#ADD8E6','#DC143C','#FFC0CB']#顏色列表
編寫繪圖函式:傳入的引數是對於起始日期所經過的天數。通過 t + datetime.timedelta(days=date) 計算需要繪製的指定天數的日期,再利用 strftime("%Y-%m-%d") 將其還原為日期文字,然後通過該日期文字取出當天的資料存入新的 df_ 中。下一步即為通過 barh 方法繪製條形圖,且每次畫新圖前需清空上一次的影象。
defdraw(date):
#資料處理------
current_date=(t+datetime.timedelta(days=date)).strftime("%Y-%m-%d")
df_=df[df['日期文字'].eq(current_date)]
days=df_['天數']
item=df_["專案"]
#繪製條形圖------
ax.clear()#重繪
#foriinrange(1,len(itme.uni))
ax.barh(item,days,color=colors)
如此之後,呼叫 draw(19) 來畫出經過19天后,也就是第20天的影象,通過 plt.show() 臨時檢視一下。
和最終效果圖還有一定的差距,多了座標軸標籤,少了系列標籤、資料標註和右上角的滾動時間。繼續完善 draw 函式:
fory,(x,name)inenumerate(zip(days.values,item.values)):#系列標註
ax.text(x,y,"%s"%x,size=12)
ifx>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 啦!
(不不不,慢著慢著)如果真要這樣做就太麻煩了,下面該祭出這次的主角了!
importmatplotlib.animationasani
matplotlib 庫提供了動態繪圖的模組,可以幫助我們更加輕鬆的製作 gif。只需傳入模型、繪圖函式、和一個 int 型別的列表即可,因此最初設計 draw 函式時所需的引數是天數 date。interval 引數為繪製每張圖的時間間隔,用於在 plt.show() 中檢查效果。最終儲存 gif 影象時可以通過 fps 引數設定幀數。
timeSlot=[xforxinrange(0,20)]#時間軸
animator=ani.FuncAnimation(fig,draw,frames=timeSlot,interval=100)
animator.save('test.gif',fps=10)
附完整程式碼:
importmatplotlib.pyplotasplt
importmatplotlib.animationasani
importpandasaspd
importdatetime
df=pd.read_excel("資料.xlsx")
df['日期文字']=df['日期'].apply(lambdax:str(x)[:10])
t=datetime.datetime(2020,1,1)#起始日期
fig,ax=plt.subplots(figsize=(10,6))#畫布
plt.rcParams['font.sans-serif']=['MicrosoftYaHei']#字型設為微軟雅黑
timeSlot=[xforxinrange(0,20)]#時間軸
colors=['#ADD8E6','#DC143C','#FFC0CB']#顏色列表
defdraw(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)
fory,(x,name)inenumerate(zip(days.values,item.values)):#系列標註
ax.text(x,y,"%s"%x,size=12)
ifx>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)
二、定製二維碼
不解釋!(看註釋)直接上程式碼:
fromMyQRimportmyqr#需先安裝MyQR庫
defQR_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=[xforxinrange(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:0auto;
width:370px;
height:220px;
position:relative;
z-index:1;
}
.show_txt{/*顯示文字*/
margin:0auto;
background-color:azure;
width:370px;
height:200px;
position:relative;
text-align:center;
padding-top:10px;
z-index:1;
}
</style>
</head>
然後在 body 裡讓它們顯示出來:
<body>
<divclass="process_gif"id="process"></div>
<divclass="show_txt"id="content_1"></div>
</body>
編寫 js 指令碼實現列印功能,在頁面載入時就呼叫列印函式 typing,並且在動態圖播放到最後一幅時,將其替換成靜態圖:
<scripttype="text/javascript">
///顯示文字功能----------------------------------
letdivTyping=document.getElementById('content_1');//通過id獲取div節點
leta=0;
timer=0;
str="我們已經相遇20天<br>告白後過了13天<br>FirstKiss至今5天";
functiontyping(){
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>
來看一下,真的是真的.真.最終效果圖:
PS:如有需要Python學習資料的小夥伴可以加下方的群去找免費管理員領取
可以免費領取原始碼、專案實戰視訊、PDF檔案等
本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯絡我們以作處理。
作者:凹凸資料