css3中實現動畫通常有兩種方式,一個是transition
過渡,一個是animation
動畫。最主要區別就是transition
須要條件觸發,一般會用hover
來觸發,而animation
則更靈活,能夠自動播放,也能夠經過條件觸發。css
那麼,如何實現一個元素出現動畫呢?css3
若是是transition
,能夠很輕鬆的實現這一效果,例如瀏覽器
.box{ visibility:hidden; opacity:0; transform:translateY(100px); transition:.3s; } .show{ visibility:visible; opacity:1; transform:translateY(0); }
這樣就實現了一個「從下至上,透明度從0至1」的出現動畫,很經常使用不是嗎。app
https://codepen.io/xboxyan/pe...框架
固然,咱們也能夠用animation
來實現,dom
.box{ visibility:hidden; opacity:0; transform:translateY(100px); transition:.3s; } .show{ animation:show .5s forwards; } .hide{ visibility:visible; opacity: 1; transform: translateY(0); animation:hide .5s forwards; } @keyframes show{ to { visibility:visible; opacity: 1; transform: translateY(0) } } @keyframes hide{ to { visibility:hidden; opacity: 0; transform: translateY(100px) } }
個人天,竟然要寫這麼多,才能實現和上面同樣的效果,沒辦法,出現和消失是兩組不一樣的動畫,因此須要定義兩個動畫。ide
https://codepen.io/xboxyan/pe...性能
上面簡單的介紹了動畫的兩種實現方法。嚴格來說,transition
只是過渡,只是切換樣式過程當中有動畫的效果,而animation
纔是真正作動畫的。固然也須要根據本身的實際需求來選擇。測試
下面來看這樣一個需求:動畫
一般頁面上要全局顯示一個消息提示,相似於toast
效果。這是我一般的作法
function showMessage(txt){ this.timer && clearTimeout(this.timer); var oDiv = document.getElementById('messageInfo'); if(!oDiv){ oDiv = document.createElement('div'); oDiv.className = 'messageInfo'; oDiv.id = 'messageInfo'; document.body.appendChild(oDiv); } oDiv.innerHTML = '<span>'+txt+'</span>'; oDiv.classList.add('show'); this.timer = setTimeout(function(){ oDiv.classList.remove('show'); },2000) }
原理就是,向頁面添加一個div#messageInfo
容器,而後添加類名.show
讓元素出現,2s後自動移除.show
實現隱藏,效果以下
https://codepen.io/xboxyan/pe...
能夠很明顯的看到一個效果就是,第一次出現的時候是沒有動畫的,之後就正常了。可能平時項目中,這一點小瑕疵也沒什麼影響,畢竟很大一部分人連動畫都不給啊,直接就是display:none
和display:block
,能夠說是提不上體驗了。
那麼,爲何會出現這種現象呢?
首先明白一點,transition
是不會自動觸發的,上面是經過添加和移除類名來實現過渡效果的。可是在第一次元素剛剛建立的時候,此時在頁面上該元素還未加載完成,這個時候當即添加類名,實際上是能夠等同因而一塊兒建立的,沒有造成過渡效果。解決這個問題很簡單,就是稍微延時一下
//... setTimeout(function(){ oDiv.classList.add('show'); },50) //...
這樣就基本上解決了這個問題,以下
https://codepen.io/xboxyan/pe...
可是,理論上這裏的延遲越小越好,我測試了一下,大概和瀏覽器的性能有關吧,用定時器的目的也僅僅是等待元素加載完成,而dom也沒有原生監聽加載完成事件,因此只能用定時器估一個大概的值。
可是,這仍然是一個瑕疵,從代碼結構上來說,這也是沒法忍受的。那麼,還有沒有更好的方法呢?答案就是animation
雖然從開頭的例子來看,animation
的寫法又臭又長,可是也正體現出它的功能強大,其中之一就是自動播放動畫
那麼,把上面的toast
改造一下,用animation
實現
.messageInfo{ /**...**/ animation:show .5s forwards; } .hide{ visibility:visible; opacity: 1; transform: translateY(0); animation:hide .5s forwards; } @keyframes show{ to { visibility:visible; opacity: 1; transform: translateY(0) } } @keyframes hide{ to { visibility:hidden; opacity: 0; transform: translateY(-100%) } }
js基本和以前一致
function showMessage(txt){ this.timer && clearTimeout(this.timer); var oDiv = document.getElementById('messageInfo'); if(!oDiv){ oDiv = document.createElement('div'); oDiv.className = 'messageInfo'; oDiv.id = 'messageInfo'; document.body.appendChild(oDiv); } oDiv.innerHTML = '<span>'+txt+'</span>'; oDiv.classList.remove('hide');//默認是顯示 this.timer = setTimeout(function(){ oDiv.classList.add('hide');//2s後隱藏 },2000) }
效果以下
https://codepen.io/xboxyan/pe...
能夠說是至關完美了
元素添加動畫
一般在添加表單或者上傳圖片時,若是須要讓新添加的元素產生一個動畫效果,那麼能夠用到animation
https://codepen.io/xboxyan/pe...
固然,還能夠作到分頁加載動畫,須要給每一個元素添加一個延時animation-delay
便可
/*animation-delay*/ .list li:not(.hide):nth-child(5n + 1) { animation-delay: .3s; } .list li:not(.hide):nth-child(5n + 2) { animation-delay: .6s; } .list li:not(.hide):nth-child(5n + 3) { animation-delay: .9s; } .list li:not(.hide):nth-child(5n + 4) { animation-delay: 1.2s; } .list li:not(.hide):nth-child(5n + 5) { animation-delay: 1.5s; }
效果以下,元素會依次登場,預覽窗口比較小,建議在原連接查看
https://codepen.io/xboxyan/pe...
而後,還能夠實現九宮格動畫,讓元素在出現的時候從左上方依次向右下方擴散,一樣是用到了animation-delay
https://codepen.io/xboxyan/pe...
很酷炫不是嗎,無需用到js,也無需用到其它框架,純自然,支持的瀏覽器體驗更上一層樓,不支持的瀏覽器也無傷大雅
整體來講,animation
遠比transition
要強大的多,固然在實際使用中也要分場景(好比文章開頭的那個例子很明顯就是transition
更好),若是有交互,如鼠標移入,首先看transition
可否實現,其次纔是animation
,若是像這一類元素出現(生成)動畫,那麼就須要使用到animation
了。