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

在本系列的第一篇文章中我們對transition動畫有了基礎的了解,本節我們將通過為圖標元素創建動畫效果,以此來著重學習另一種動畫製作方法:animation動畫。因此,本節的主題就是animation動畫的理解與運用。

什麼是animation動畫?

和transition動畫一樣,animation動畫也是CSS3動畫的一種。這類動畫可以理解為是一種關鍵幀動畫,它可以預先為動畫設置多個節點,在每個節點中含有不同的狀態屬性,通過使用animation動畫我們可以得到更為複雜的動畫效果。

複習一下:transition是為頁面元素設置某個需要產生動畫效果的屬性,如寬度(width)、高度(height)、透明度(opacity),甚至3D旋轉等,並使得這些屬性的值在發生變化時產生相應的過渡效果。我們常常在製作類似按鈕滑鼠經過和移出效果時使用transition。通俗地說,transition是簡化版的CSS3動畫,而animation則是強化版的CSS3動畫。在日常開發中transition的使用頻率更高一些,我們往往只有在遇到transition無法解決的問題時,才會轉而使用animation。

DOM和CSS的準備

nnnnnnnnnnnnnnn首先,準備一個span元素作為圖標的載體(也可以使用其他元素,如div、a、button等)。代碼如下:

<span class="close">Close</span>n

在此我們使用設置了icon字體的偽元素來生成圖標圖案,代碼如下:

nnnnnnnnnnnnnnn

.close{ntfont-size:0px; /*使span中的文字不顯示*/ntcursor:pointer; /*使滑鼠指針顯示為手型*/ntdisplay:block;ntwidth:100px;ntheight:100px;ntline-height:100px;ntborder-radius:50%; /*使背景形狀顯示為圓形*/ntbackground:#FFF;ntcolor:#8b8ab3;nttext-align:center;n}n.close::before{ntcontent:"e609";ntfont-family: icon-font;ntspeak:none; /*使文本內容不能通過屏幕閱讀器等輔助設備讀取*/ntfont-size:48px;ntdisplay:block;n}n

在以上代碼中繪製了一個圓形按鈕,其原理是通過設置span原本的字體大小為0來隱藏「Close」文字,並通過設置屬性值為50%的圓角來實現圓形效果。此外,我們還添加了speak:none屬性來為該元素增強可訪問性,使得有閱讀障礙的瀏覽者不會被插入的偽元素中的無意義字元所困擾。圓形圖標效果如圖所示。

初試animation動畫

接下來,我們為滑鼠指針的滑過狀態設置一些動畫效果。在此,我們希望當滑鼠指針滑過時,圖標在1秒內勻速旋轉360度。我們在此先複習一下transition動畫的用法,代碼如下:

.close:hover::before{nt-webkit-transform:rotate(360deg);nttransform:rotate(360deg);nt-webkit-transition:-webkit-transform 1s linear;nttransition:transform 1s linear;n}n

nnnnnnnnnnnnnnn在以上代碼中,我們使用了transform屬性來實現圖標的旋轉,並且設置了transition動畫,將變化的屬性名稱設置為transform。測試頁面,現在我們將看到圖標的旋轉效果,如圖所示。

注意:在設置旋轉屬性時,需要加上deg作為度數單位,即使是旋轉0度也需要同樣添加這一單位。此外,transform只是一種變換屬性,其本身不能生成動畫效果,它只能通過與transition或animation屬性的配合才能產生動畫效果。

當前的圖標只會旋轉一次,然後將停止下來。而如果我們希望圖標能夠一直不停旋轉,則需要請出animation動畫。使用animation動畫的前提是先製作動畫的各個關鍵幀,代碼如下:

@-webkit-keyframes spin { /*兼容性寫法*/ntfrom {ntt-webkit-transform: rotate(0deg);nt}ntto {ntt-webkit-transform: rotate(360deg);nt}n}n@keyframes spin {ntfrom {ntttransform: rotate(0deg);nt}ntto {ntttransform: rotate(360deg);nt}n}n

在以上代碼中,我們使用了keyframes關鍵字來定義了一個名為spin的關鍵幀動畫,在該動畫中使用了from關鍵字來指定動畫的起始狀態,to關鍵字來指定動畫的結束狀態。在起始狀態中設置transform屬性的旋轉度為0度,在結束狀態中設置該旋轉度為360度。此外,我們還添加了-webkit-前綴以確保動畫在webkit瀏覽器中的兼容性。

在指定了spin關鍵幀動畫後,我們就可以在圖標中運用這一動畫,代碼如下:

.close:hover::before{nt-webkit-animation: spin 1s linear;ntanimation: spin 1s linear;n}n

nnnnnnnnnnnnnnn在以上代碼中,我們設置了滑鼠滑過狀態下偽元素的animation屬性,該屬性的第一個參數是動畫名稱,即spin,第2個參數是動畫時長,在此設置為1秒,第3個屬性為速度曲線,在此設置為勻速運動。測試頁面,現在我們能夠得到和之前transition動畫相同的效果,如圖所示。

給animation動畫添加各種參數

如果我們希望圖標一直旋轉,則可以在animation屬性中添加infinite參數,代碼如下:

.close:hover::before{nt-webkit-animation: spin 1s linear infinite;ntanimation: spin 1s linear infinite;n}n

nnnnnnnnnnnnnnn以上代碼中,infinite參數表示動畫將無限循環。如果我們只希望動畫循環一定次數,則可以將其修改為相應的數字。例如,要使圖標360度旋轉兩次,代碼如下:

.close:hover::before{nt-webkit-animation: spin 1s linear 2;ntanimation: spin 1s linear 2;n}n

在速度曲線和播放次數之間還可以插入一個時間參數,用以設置動畫延遲的時間。如希望使圖標在1秒鐘後再開始旋轉,並旋轉兩次,代碼如下:

.close:hover::before{nt-webkit-animation: spin 1s linear 1s 2;ntanimation: spin 1s linear 1s 2;n}n

我們還可以在animation動畫中加入反向播放參數alternate。在加入該參數後,動畫將在偶數次數時反向播放動畫。如在之前代碼中,圖標將順時針旋轉兩次,而加入alternate後,則變為順時針旋轉一次後,再逆時針旋轉一次,代碼如下:

.close:hover::before{nt-webkit-animation: spin 1s linear 1s 2 alternate;ntanimation: spin 1s linear 1s 2 alternate;n}n

animation動畫序列

nnnnnnnnnnnnnnnnn

在以上的animation屬性參數中,延遲參數是我們較為常用的一種參數。當動畫的對象為多個時,我們常常用延遲參數來形成動畫序列。如以下代碼定義了5個不同的圖標:

<span class="home icon">Home</span>n<span class="search icon">Search</span>n<span class="user icon">User</span>n<span class="mail icon">Mail</span>n<span class="chat icon">Chat</span>n

圖標的基本樣式和之前的Close圖標一致,不同之處在於此處的圖標都設置為inline-block,使它們能夠橫向排列。代碼如下:

.icon{ntdisplay:inline-block;ntmargin-right:20px;n}n.home::before{ntcontent:"e62e";n}n.search::before{ntcontent:"e630";n}n/*其餘偽元素content屬性設置略過*/n

圖標的初始顯示效果如圖所示。

接下來,為圖標添加animation動畫,使圖標初始位置向下偏移-100%,然後再向上移動回到初始位置,在此過程中同時使圖標由完全透明變化為完全不透明,代碼如下:

.icon{nt-webkit-animation:move 1s;ntanimation:move 1s;n}n@-webkit-keyframes move {ntfrom {nttopacity:0;ntt-webkit-transform:translateY(100%);nt}ntto {nttopacity:1;ntt-webkit-transform:translateY(0%);nt}n}n@keyframes move {ntfrom {nttopacity:0;ntttransform:translateY(100%);nt}ntto {nttopacity:1;ntttransform:translateY(0%);nt}n}n

在以上代碼中,我們使用了transform屬性的translateY方法來實現圖標的向下偏移,並使用opacity屬性來設置圖標的透明度。動畫效果如圖所示。

以上5個圖標的動畫效果都是同時進行的,為了使圖標運動帶有先後順序,我們將為每個動畫添加延遲。和之前運用的方法所不同,我們可以直接通過animation-delay屬性來設置animation動畫延遲,代碼如下:

.home{nt-webkit-animation-delay:0s;ntanimation-delay:0s;n}n.search{nt-webkit-animation-delay:.1s;ntanimation-delay:.1s;n}n.user{nt-webkit-animation-delay:.2s;ntanimation-delay:.2s;n}n.mail{nt-webkit-animation-delay:.3s;ntanimation-delay:.3s;n}n.chat{nt-webkit-animation-delay:.4s;ntanimation-delay:.4s;n}n

在以上代碼中,我們設置了5個圖標的延遲時間分別為0、0.1、0.2、0.3和0.4s。實際上,延遲0秒為默認值,因此第一個圖標實際上也不需要設置延遲代碼。測試頁面,動畫效果如圖所示。

「靈異」事件的解決之道

以上效果所呈現的延遲運畫效果似乎已經非常完美,5個圖標依次出現並向上運動到最終的位置。然而,當我們仔細看動畫的整個過程,會發現在動畫的最開頭,幾個圖標將在頂部一閃而過,如圖所示。

發生這種「靈異」事件的原因在於除第一個圖標外,其餘圖標都有一定的動畫延遲,而在動畫沒有開始時,圖標是沒有發生偏移,也是完全不透明的,只有當動畫開始的那一瞬間,圖標才會切換到完全透明且偏移的動畫起始狀態。

那麼如何解決這一問題呢?或許我們可以嘗試使5個圖標默認狀態就是發生偏移且完全透明的,但即使這樣修改後,測試頁面時我們會發現,動畫開頭的閃現問題消失了,而新的問題又發生了,當動畫結束後,5個圖標又回到了其默認狀態,即全部消失不見了。

nnnn要解決這一問題,就需要使用animation動畫的animation-fill-mode屬性。這一屬性規定了元素在動畫時間之外的狀態是怎樣的。若該值為forwards,則表示動畫完成後保留最後一個關鍵幀中的屬性值,該值為backwards時則恰好相反,表示在動畫延遲之前就使得元素應用第一個關鍵幀中的屬性值,而該值為both時則表示同時包含forwards和backwards兩種設置。在本例中,我們使用backward或both均可,代碼如下:

.icon{n -webkit-animation-fill-mode:both;n animation-fill-mode:both;n}n

現在,再次測試頁面,圖標的閃現問題就得到了完美的解決,如圖所示。

速度曲線的設置

nnnnnnnnnnnnnnnnn

在animation中也可以像transition動畫那樣設置速度曲線。CSS3動畫中默認的ease效果本來就很不錯,因此我們往往省略了對於速度曲線的設置。而在一些非常自定義的動畫中,我們也可以考慮運用速度曲線來實現一些特殊的效果。

nn

例如,在本例中我們希望圖標的運動帶有一點彈性效果,即圖標向上運動時,並非減速並停止在終點,而是到達終點後繼續向上運動,超過一定距離後再反方向運動回到終點,形成一種往複的效果。我們當然可以使用幀動畫來實現這樣的效果,但是如果使用速度曲線將更為簡便。要使用自定義曲線,我們往往需要一些工具,因為CSS3動畫使用了三次貝塞爾(Cubic Bezier)數學函數來生成速度曲線,而這個函數的參數並不直觀。我們可以使用諸如cubic-bezier.com這樣的站點來可視化地調整速度曲線,如圖所示。

cubic-bezier.com中,我們可以通過拖動兩個控制點來調整速度的曲率,最終生成的貝塞爾函數將依次包括兩個控制點的x和y位置。其中x位置的範圍在0和1之間,y位置則既可以在0和1之間,也可以大於或小於這個數值範圍。

nn為了實現彈性效果,我們將第一個控制點拖動到(.62,-0.91)的位置,將第二個控制點拖動到(.45,1.97)的位置,形成的速度曲線如圖所示。

接下來,我們就能夠將該速度曲線寫入animation屬性的參數中,代碼如下:

.icon{n -webkit-animation:move 1s cubic-bezier(.62,-0.91,.45,1.97);n animation:move 1s cubic-bezier(.62,-0.91,.45,1.97);n}n

現在,測試頁面,我們就能得到彈性的動畫效果了,動畫的結尾效果如圖所示。

THE END

廣告:

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

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

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

推薦閱讀:

來聊聊6到飛起的動畫工作室madhouse!
【動漫精選】豆瓣9.3,這部奇番讓你看盡人心的荒誕!
每個人心裡都有一團火,路過的人卻只看到煙
如何評價《天降之物》的伊卡洛斯?

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