JS動畫和CSS動畫
一. JS動畫和CSS動畫區別。
CSS實現動畫:animation transition transform
JS實現動畫:setInterval setTimeout requestAnimationFrame
JS動畫:
優點:
1. 過程控制,可以在動畫播放過程中對動畫進行控制:開始、暫停、回放、終止、取消都是可以做到的。
2. 動畫效果比css3動畫豐富,有些動畫效果,比如曲線運動,沖擊閃爍,視差滾動效果,只有JavaScript動畫才能完成。
3. CSS3有兼容性問題,而JS大多時候沒有兼容性問題。
缺點:
1. JavaScript在瀏覽器的主線程中運行,而主線程中還有其它需要運行的JavaScript腳本、樣式計算、布局、繪制任務等,對其幹擾導致線程可能出現阻塞,從而造成丟幀的情況。
2. 代碼的復雜度高於CSS動畫。
CSS動畫:
優點(瀏覽器可以對動畫進行優化):
1. 集中所有DOM,一次重繪重排,刷新頻率和瀏覽器刷新頻率相同。
2. 代碼簡單,方便調試
3. 不可見元素不參與重排,節約CPU
4. 可以使用硬件加速(通過 GPU 來提高動畫性能)。
缺點:
1. 運行過程控制較弱,無法附加事件綁定回調函數。
CSS動畫只能暫停,不能在動畫中尋找一個特定的時間點,不能在半路反轉動畫,不能變換時間尺度,不能在特定的位置添加回調函數或是綁定回放事件,無進度報告。
2. 代碼冗長。
CSS動畫流暢的原因
渲染線程分為main thread(主線程)和compositor thread(合成器線程)。
如果CSS動畫只是改變transform
和opacity,
這時整個CSS動畫得以在compositor thread完成(而JS動畫則會在main thread執行,然後觸發compositor進行下一步操作),所以,當在JS執行一些昂貴的任務時,main thread繁忙,CSS動畫由於使用了compositor thread可以保持流暢。
在主線程中,維護了一棵Layer樹(LayerTreeHost),管理了TiledLayer,
在compositor thread,維護了同樣一顆LayerTreeHostImpl,管理了LayerImpl,
這兩棵樹的內容是拷貝關系。因此可以彼此不幹擾,當Javascript在main thread操作LayerTreeHost的同時,compositor thread可以用LayerTreeHostImpl做渲染。當Javascript繁忙導致主線程卡住時,合成到屏幕的過程也是流暢的。
鼠標鍵盤消息會被首先分發到compositor thread,然後再到main thread。這樣,當main thread繁忙時,compositor thread還是能夠響應一部分消息。
例如,鼠標滾動時,假如main thread繁忙,compositor thread也會處理滾動消息,滾動已經被提交的頁面部分(未被提交的部分將被刷白)。
CSS動畫比JS流暢的前提:
- JS在執行一些昂貴的任務
- 同時CSS動畫不觸發layout或paint
在CSS動畫或JS動畫觸發了paint或layout時,需要main thread進行Layer樹的重計算,這時CSS動畫或JS動畫都會阻塞後續操作。
只有如下屬性的修改才符合“僅觸發Composite,不觸發layout或paint”:
- backface-visibility
- opacity
- perspective
- perspective-origin
- transfrom
如果動畫只是簡單的狀態切換,不需要中間過程控制,在這種情況下,css動畫是優選方案。它可以讓你將動畫邏輯放在樣式文件裏面,而不會讓你的頁面充斥 Javascript 庫。然而如果你在設計很復雜的富客戶端界面或者在開發一個有著復雜UI狀態的 APP。那麽你應該使用js動畫,這樣你的動畫可以保持高效,並且你的工作流也更可控。所以,在實現一些小的交互動效的時候,就多考慮考慮CSS動畫。對於一些復雜控制的動畫,使用javascript比較可靠。
二. animation transition transform介紹
1. transform (變形)
屬性:
rotate 旋轉:transform:rotate(-45deg),值為正數表示順時針旋轉,如果設置的值為負數,則表示逆時針旋轉。
skew 扭曲、傾斜:skew(x,y)使元素在水平和垂直方向同時扭曲(X軸和Y軸同時按一定的角度值進行扭曲變形);skewX(x)僅使元素在水平方向扭曲變形(X軸扭曲變形);skewY(y)僅使元素在垂直方向扭曲變形(Y軸扭曲變形)。同樣是以元素中心為基點,我們也可以通過transform-origin來改變元素的基點位置。如:transform:skew(30deg,10deg):
scale 縮放:scale(x,y)也就是X軸和Y軸同時縮放;scaleX(x)元素僅水平方向縮放(X軸縮放);scaleY(y)元素僅垂直方向縮放(Y軸縮放),縮放基數為1,如果其值大於1元素就放大,反之其值小於1,元素縮小。
其基點一樣是在元素的中心位置,我們同樣是通過transform-origin來改變元素的基點。
translate 移動:transform:translate(1px,2px). 使用其他單位:em,%也是可以的。
移動translate我們分為三種情況:translate(x,y)水平方向和垂直方向同時移動;translateX(x)僅水平方向移動(X軸移動);translateY(Y)僅垂直方向移動(Y軸移動)。其基點是元素中心點,也可以根據transform-origin改變基點位置。
transform-origin(X,Y):用來設置元素的運動的基點(參照點)。默認點是元素的中心點。其中X和Y的值可以是百分值,em,px,其中X也可以是字符參數值left,center,right;Y和X一樣除了百分值外還可以設置字符值top,center,bottom。其中 left,center right是水平方向取值,對應的百分值為left=0%;center=50%;right=100%而top center bottom是垂直方向的取值,其中top=0%;center=50%;bottom=100%;如果只取一個值,表示垂直方向值不變。
transform在不同瀏覽器內核下的書寫規則
//Mozilla內核瀏覽器:firefox3.5+
-moz-transform: rotate | scale | skew | translate ;
//Webkit內核瀏覽器:Safari and Chrome
-webkit-transform: rotate | scale | skew | translate ;
//Opera
-o-transform: rotate | scale | skew | translate ;
//IE9
-ms-transform: rotate | scale | skew | translate ;
//W3C標準
transform: rotate | scale | skew | translate ;
2. transition
transition可以實現動態效果,實際上是一定時間之內,一組css屬性變換到另一組屬性的動畫展示過程。
4個屬性:
(1). 要以動畫展示哪些屬性(transition-property)
none 沒有屬性改變;all所有屬性改變;indent元素屬性名;
(2). 動畫過程有多久(transition--duration),默認變換是即時的。
(3). 控制動畫速度變化(transition-timing-function)
1、ease:(逐漸變慢)默認值,ease函數等同於貝塞爾曲線(0.25, 0.1, 0.25, 1.0).
2、linear:(勻速),linear 函數等同於貝塞爾曲線(0.0, 0.0, 1.0, 1.0).
3、ease-in:(加速),ease-in 函數等同於貝塞爾曲線(0.42, 0, 1.0, 1.0).
4、ease-out:(減速),ease-out 函數等同於貝塞爾曲線(0, 0, 0.58, 1.0).
5、ease-in-out:(加速然後減速),ease-in-out 函數等同於貝塞爾曲線(0.42, 0, 0.58, 1.0)
6、cubic-bezier:(該值允許你去自定義一個時間曲線), 特定的cubic-bezier曲線。 (x1, y1, x2, y2)四個值特定於曲線上點P1和點P2。所有值需在[0, 1]區域內,否則無效。
其是cubic-bezier為通過貝賽爾曲線來計算“轉換”過程中的屬性值,如下曲線所示,通過改變P1(x1, y1)和P2(x2, y2)的坐標可以改變整個過程的Output Percentage。初始默認值為default.
(4). 動畫是否延遲執行(transition-delay)
transition速記法:transition: <property> <duration> <animation type> <delay>
3. animation
transition只能從一組css屬性變成另一組css屬性。animation則可以在多組屬性之間變換。
transition必須使用觸發器觸發,animation可以使用觸發器,也可以在頁面加載完成的時候自動觸發。
CSS3中的Animation與HTML5中的Canvas繪制動畫又不同,Animation只應用在頁面上已存在的DOM元素上,而且他跟Flash和JavaScript以及jQuery制作出來的動畫效果又不一樣,因為我們使用CSS3的Animation制作動畫我們可以省去復雜的js,jquery代碼,只是有一點不足之處,我們運用Animation能創建自己想要的一些動畫效果,但是有點粗糙,如果想要制作比較好的動畫,我見意大家還是使用flash或js等。
"Keyframes",我們把他叫做“關鍵幀”,我們在使用transition制作一個簡單的transition效果時,我們包括了初始屬性和最終屬性,一個開始執行動作時間和一個延續動作時間以及動作的變換速率,其實這些值都是一個中間值,如果我們要控制的更細一些,比如說我要第一個時間段執行什麽動作,第二個時間段執行什麽動作(換到flash中說,就是第一幀我要執行什麽動作,第二幀我要執行什麽動作),這樣我們用Transition就很難實現了,此時我們也需要這樣的一個“關鍵幀”來控制。那麽CSS3的Animation就是由“keyframes”這個屬性來實現這樣的效果。
@-webkit-keyframes ‘wobble‘ { 0% { margin-left: 100px; background: green; } 40% { margin-left: 150px; background: orange; } 60% { margin-left: 75px; background: blue; } 100% { margin-left: 100px; background: red; } }
wobble動畫在0%時元素定位到left為100px的位置背景色為green,然後40%時元素過渡到left為150px的位置並且背景色為orange,60%時元素過渡到left為75px的位置,背景色為blue,最後100%結束動畫的位置元素又回到起點left為100px處,背景色變成red。
CSS3的animation類似於transition屬性,他們都是隨著時間改變元素的屬性值。他們主要區別是transition需要觸發一個事件(hover事件或click事件等)才會隨時間改變其css屬性;而animation在不需要觸發任何事件的情況下也可以顯式的隨著時間變化來改變元素css的屬性值,從而達到一種動畫的效果。這樣我們就可以直接在一個元素中調用animation的動畫屬性,基於這一點,css3的animation就需要明確的動畫屬性值,這也就是回到我們上面所說的,我們需要keyframes來定義不同時間的css屬性值,達到元素在不同時間段變化的效果。
下面我們來看看怎麽給一個元素調用animation屬性 .demo1 { width: 50px; height: 50px; margin-left: 100px; background: blue; -webkit-animation-name:‘wobble‘;/*動畫屬性名,也就是我們前面keyframes定義的動畫名*/ -webkit-animation-duration: 10s;/*動畫持續時間*/ -webkit-animation-timing-function: ease-in-out; /*動畫頻率,和transition-timing-function是一樣的*/ -webkit-animation-delay: 2s;/*動畫延遲時間*/ -webkit-animation-iteration-count: 10;/*定義循環資料,infinite為無限次*/ -webkit-animation-direction: alternate;/*定義動畫方式*/ }
animation屬性:
(1) animation-name創建一個動畫名稱:
- none為默認值,當值為none時,將沒有任何動畫效果。
- IDENT是由Keyframes創建的動畫名,換句話說此處的IDENT要和Keyframes中的IDENT一致,如果不一致,將不能實現任何動畫效果
(2) animation-duration:
(3) animation-timing-function;
(4) animation-delay;
(5) animation-iteration-count: 是用來指定元素播放動畫的循環次數,其可以取值<number>為數字,其默認值為“1”;infinite為無限次數循環。
(6) animation-direction:
- 默認值為normal: 動畫的每次循環都是向前播放;
- alternate,動畫播放在第偶數次向前播放,第奇數次向反方向播放。
(7) animation-play-state:是用來控制元素動畫的播放狀態。
- running為默認值:
- paused將正在播放的動畫停下
(8) animation-fill-mode:告訴瀏覽器將元素的格式保持為動畫結束時候的樣子。
JS動畫和CSS動畫