【前端入門系列】HTML5動畫與動效(之三)

在本系列的前兩篇文章中我們分別對transition和animation動畫有了基礎的了解,這兩種動畫基本都是基於某種「屬性參數變化」的動畫。而當我們需要製作一些通過屬性變化無法實現的動畫效果時,就需要使用逐幀動畫。在本篇教程中我們將介紹簡單的逐幀動畫做法,通過製作一段簡單的跑步動畫來演示HTML5中以圖片序列來實現逐幀動畫效果的方法。

逐幀圖片繪製

nnnnnnnnnnnnnnn首先,在Illustrator之類的矢量繪圖軟體中繪製好跑步動作的每一個環節。

創建逐幀動畫時,最方便的是使得每一幀的動畫都有著相同的大小,我們可以在PhotoShop中完成這一尺寸調整。在此我們將每一幀的內容都設置為300*372像素的寬高。

將以上圖像存為PNG圖片,命名為run.png。現在,逐幀圖片就製作完成了。

由於其中包含了12幀動畫,每一幀為300*372像素,則該run.png文件尺寸為3600*372像素。

CSS樣式製作

nnnnnnnnnnnnnnn接下來,我們回到HTML文件,為跑步動畫準備一個DOM容器,代碼如下:

<div class="run"></div>n

然後,設置run類的CSS樣式,將run.png作為背景,且不重複平鋪,設定好容器的寬度和高度,使得在該大小範圍內正好能夠顯示出一幀動畫。代碼如下:

nnnnnnnnnnnnnnnnnnn

.run {ntwidth: 300px;ntheight: 372px;ntbackground: url(run.png) no-repeat;n}n

nnnnnnnnnnnnnnn測試頁面,現在我們只能看到第一幀的動畫內容。

添加animation動畫

逐幀動畫的基本思路就是通過移動背景圖片的位置,來實現圖片的切換,進而呈現齣動畫效果。由於我們的動畫一共有12幀,加上動畫開頭和結尾是同樣的兩個節點,因此一共需要有13個節點,將100%平均分為13份,則可以得到每個節點的百分比值依次為0%、8.3%、16.7%...100%。在每個節點中,我們只需設置background-position屬性,使圖片依次向左移動300像素即可。代碼如下:

@keyframes run {nt0%, 100% {nttbackground-position:0 0;nt}nt8.3% {nttbackground-position:-300px 0;nt}nt16.7% {nttbackground-position:-600px 0;nt}nt25% {nttbackground-position:-900px 0;nt}nt33.3% {nttbackground-position:-1200px 0;nt}nt41.7% {nttbackground-position:-1500px 0;nt}nt50% {nttbackground-position:-1800px 0;nt}nt58.3% {nttbackground-position:-2100px 0;nt}nt66.7% {nttbackground-position:-2400px 0;nt}nt75% {nttbackground-position:-2700px 0;nt}nt83.3% {nttbackground-position:-3000px 0;nt}nt91.7% {nttbackground-position:-3300px 0;nt}n}n

為了精簡篇幅,以上代碼中我們略去了-webkit-的兼容性寫法。接下來,我們為run類設置animation屬性,將動畫時長設置為900毫秒,並無限循環,代碼如下:

.run {nt-webkit-animation: run 900ms infinite;ntanimation: run 900ms infinite;n}n

測試頁面,我們並沒有得到預想中的逐幀動畫效果,而是背景圖片一直向右快速移動的效果。

讓動畫平滑起來

nnnnnnnnnnnnnnn我們也很容易理解這一效果的產生原因,animation默認背景圖片位置在水平方向上發生了位移,因此整個動畫過程是以平滑的形式呈現的。我們要使其「一格一格」地顯示,則可以使用animation動畫的steps方法,使得每一個動畫關鍵幀都以「台階」而非「線性」的形式顯示,代碼如下:

.run {nt-webkit-animation: run 900ms steps(1) infinite;ntanimation: run 900ms steps(1) infinite;n}n

現在再次測試頁面,我們就能夠看到流暢的逐幀動畫了。

逐幀的另一種製作思路

nnnnnnnnnnnnnnn除以上的背景位置切換方式外,我們也可以用多張圖片交替呈現的方式製作逐幀動畫。

首先,我們要將每一幀單獨保存為一個文件,在此可以使用PhotoShop中的切片工具來快速完成該操作。

nnnnnnnnnnnnnnn當完成切片後,我們可以將圖片以HTML和圖像的形式保存,PhotoShop會自動生成單張且序列化命名的圖片文件。

接下來,我們要準備12個div元素,每個div元素用於放置一張圖片,其id屬性名依次為frame1至frame12,代碼如下:

nnnnnnnnnnnnnnn

<div class="run">n <div id="frame1" class="run-pic"></div>n <div id="frame2" class="run-pic"></div>n ...n <div id="frame11" class="run-pic"></div>n <div id="frame12" class="run-pic"></div>n</div>n

nnnnnnnnnnnnnnn接著,使每一個div都以絕對定位的方式顯示在run容器的左上角,並為這些div分別設置背景圖片。

.run {ntwidth:300px;ntheight:372px;ntposition:relative;n}n.run-pic{ntposition:absolute;ntwidth:300px;ntheight:372px;ntdisplay:block;nttop:0;ntleft:0;n}n#frame1{ntbackground:url(images/run_01.png);n}n#frame2{ntbackground:url(images/run_02.png);n}n/*省略其它代碼*/n#frame12{ntbackground:url(images/run_12.png);n}n

最後,我們使用jQuery來實現動畫效果。我們的製作思路是首先將12張圖片全部隱藏,然後將第一張圖片顯示,停留0.1秒後隱藏,第二張圖片則延遲0.1秒顯示,剛好接上第一張圖片隱藏,第三張圖片延遲0.2秒,以此類推。所有12張圖片全部顯示完畢後,第一張圖片再次顯示,因此兩次動畫輪迴間需要延遲的時間是其餘11張圖片的顯示時間,即1.1秒。我們可以創建一個loop函數供反覆調用,以生成這一動畫輪迴,而在動畫最開始時,則需要通過遍歷div元素,為每個元素設置初始的延遲值。代碼如下:

nnnnnnnnnnnnnnnnnnn

<script type="text/javascript">nt$(document).ready(function() {ntt$(.run-pic).each(function(index){nttt$(this).hide(0).delay(index*100).show(0,loop);ntt});nt});ntfunction loop(){ntt$(this).delay(100).hide(0).delay(1100).show(0,loop);nt}n</script>n

在以上代碼中,每張圖片都立即調用hide(0)方法,馬上隱藏起來,繼而通過delay()方法實現延遲,延遲的時間等於索引值乘以100,因此第一張圖片延遲0毫秒,第二張圖片延遲100毫秒,第三張圖片延遲200毫秒...在經過了延遲時間後,該圖片再通過調用show()方法來顯示,此時也調用了loop函數,使圖片開始進入動畫的輪迴。測試頁面,我們將得到與之前的CSS動畫完全相同的逐幀動畫效果。

小結

nnnnnnnnnnnnnnnnnnn與CSS動畫相比,使用JavaScript創建逐幀動畫有利也有弊,其弊端是製作過程更加複雜一些,其有利之處在於它對動畫的控制能力更強,同時能夠呈現更加複雜的動畫效果。在實戰開發中我們應該根據實際情況靈活地選擇動畫的實現方式。

此外,除以上兩種方式外,我們還可以使用Canvas畫布來繪製逐幀動畫,在後續文章中將詳細介紹具體實現方法。

nnnnnnnnnnnnnnn

本例源文件:cloud.ecnu.edu.cn/p/DUD

THE END

廣告:

個人新書 《HTML5基礎知識、核心技術與前沿案例》,噹噹、京東、亞馬遜有售。

噹噹:《HTML5基礎知識 核心技術與前沿案例》(劉歡)

京東:《HTML5基礎知識 核心技術與前沿案例》(劉歡)


推薦閱讀:

實力至上教室第6話:b霸就要拿出應有的實力。
如何評價光學核心的個人動畫《高溫vs排斥》?
凝視與幻影:今敏《未麻的房間》文本細讀
如何評價FLCL將出續作?
朋友,你還記得這些童年陰影嗎?

TAG:HTML5 | 前端开发 | 动画 |