# CSS動畫
## **一、 定義和用法**
一些 CSS 屬性是*可以有動畫效果的*,這意味著它們可以用于動畫和過渡。
動畫屬性可以逐漸地從一個值變化到另一個值,比如尺寸大小、數量、百分比和顏色。
## **二、瀏覽器支持**
表格中的數字表示支持該方法的第一個瀏覽器的版本號。
緊跟在數字后面的 -webkit-, -moz-, 或 -o- 指定了第一個支持該屬性的瀏覽器版本前綴。

## **三、Transition**
1. **基本用法**
```
div {
width: 200px;
height: 200px;
background-color: red;
}
div:hover {
width: 500px;
height: 500px;
}
<div>我是一個盒子</div>
```
代碼掩飾的是當鼠標放置于div上 div會迅速變大。變大的是瞬間實現的。
使用 ```transition```可以**指定狀態變化所需要的時間**
```
div {
width: 200px;
height: 200px;
background-color: red;
transition: 5s;
}
//此時可以發現,div變大的過程中 變化有了時間梯度,即5秒鐘變大 不是干蹦效果了
```
可以設置單項的動畫效果 如:```div { transition: 5s height; }``` 效果為:高度變化的時候有個平滑的過度,而寬度則還是干蹦變化
2. **transition-delay**
在同一行```transition```中,可以分別指定多個屬性,想要的效果是height先發生變化后,width再發生變化,就是為width指定一個delay參數
```div { transition: 5s height, 1s 5s width; }``` [逗號后的第一個參數是動畫過渡時間,第二個參數是delay的時間],delay的真正意義就是指定了動畫的發生順序
3. **transtion-timing-function**
transition的狀態變化速度(又稱timing function),默認不是勻速的,而是逐漸放慢,這叫做```ease```。
```div { transition: 1s ease };```
其他的模式:
```
linear: 勻速
ease-in : 加速
ease-out: 減速
cubic-bezier函數: 自定義速度模式 //貝塞爾曲線
```
貝塞爾曲線
cubic-bezier稱為三次貝塞爾曲線,主要是生成速度曲線的函數,規定是```cubic-bezier(<x1>,<y1>,<x2>,<y2>)```
```
//會產生一個最后階段放大過度然后回縮的效果
div {
transition: 1s height cubic-bezier(.83,.97,.05,1.44);
}
```


>從上圖中我們可以看到,cubic-bezier有四個點:
兩個默認的,即:P0(0,0),P3(1,1);
兩個控制點,即:P1(x1,y1),P2(x2,y2)
注:X軸的范圍是0~1,超出cubic-bezier將失效,Y軸的取值沒有規定,但是也不宜過大。
我們只要調整兩個控制點P1和P2的坐標,最后形成的曲線就是動畫曲線。
4. **transition的各個屬性**
```
div {
transition: 1s 1s height ease;
}
//還可獨立定義各個屬性
div {
transtion-property: height; //規定應用過渡效果的CSS屬性名稱,過度效果通常是用戶將鼠標懸浮到元素上時發生
transition-duration: 1s; //過渡效果持續時間
transition-delay: 1s; //過渡延遲時間
transtion-timing-function: ease; //過渡函數
}
```
5. **transition的使用注意**
(1)目前,各大瀏覽器(包括IE 10)都已經支持無前綴的transition,所以transition已經可以很安全地不加瀏覽器前綴。
(2)不是所有的CSS屬性都支持transition,完整的列表查看[這里](http://oli.jp/2010/css-animatable-properties/),以及具體的[效果](http://leaverou.github.io/animatable/)。
(3)transition需要明確知道,開始狀態和結束狀態的具體數值,才能計算出中間狀態。比如,height從0px變化到100px,transition可以算出中間狀態。但是,transition沒法算出0px到auto的中間狀態,也就是說,如果開始或結束的設置是height: auto,那么就不會產生動畫效果。類似的情況還有,display: none到block,background: url(foo.jpg)到url(bar.jpg)等等。
6. **transition的局限**
transition的優點在于簡單易用,但是它有幾個很大的局限。
(1)transition需要事件觸發,所以沒法在網頁加載時自動發生。
(2)transition是一次性的,不能重復發生,除非一再觸發。
(3)transition只能定義開始狀態和結束狀態,不能定義中間狀態,也就是說只有兩個狀態。
(4)一條transition規則,只能定義一個屬性的變化,不能涉及多個屬性。
CSS Animation就是為了解決這些問題而提出的。
## 三、**Animation**
1. **基本用法**
首先,animation需要制定動畫一個周期持續的時間以及動畫效果的名稱
```
div:hover {
animation: 1s rainbow;
}
//此代碼表示,當鼠標懸停在div上會產生rainbow的動畫效果,持續時間為1s。為此,我們還需要使用keyframes關鍵字,定義rainbow效果
@keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
//rainbow效果一共有三個狀態,分別為起始(0%)、中點(50%)和結束(100%)。如果有需要,完全可以插入更多狀態。
```
**默認情況下,動畫只播放一次。加入```infinite```關鍵字,可以讓動畫無限次播放。**
~~~css
div:hover {
animation: 1s rainbow infinite;
}
~~~
**也可以指定動畫的播放次數**
~~~css
div:hover {
animation: 1s rainbow 3;
}
~~~
2. **animation-fill-mode**
動畫結束以后,會立即從結束狀態跳回到起始狀態。如果想讓動畫保持在結束狀態,需要使用```animation-fill-mode```屬性。
~~~css
//forwards表示讓動畫停留在結束狀態
div:hover {
animation: 1s rainbow forwards;
}
~~~
animation-fill-mode還可以使用下列值
>(1)none:默認值,回到動畫沒開始時的狀態。
(2)backwards:讓動畫回到第一幀的狀態。
(3)both: 根據animation-direction(見后)輪流應用forwards和backwards規則。
3. **animation-direction**
動畫循環播放時,每次都是從結束狀態跳回到起始狀態,再開始播放。animation-direction屬性,可以改變這種行為。
~~~css
@keyframes rainbow {
0% { background-color: yellow; }
100% { background: blue; }
}
~~~
默認情況是,animation-direction等于normal
~~~css
div:hover {
animation: 1s rainbow 3 normal;
}
~~~
此外,還可以等于取alternate(交替)、reverse(顛倒)、alternate-reverse等值。它們的含義見下圖(假定動畫連續播放三次)。

簡單說,animation-direction指定了動畫播放的方向,最常用的值是normal和reverse。瀏覽器對其他值的支持情況不佳,應該慎用。
4. **animation的各項屬性**
~~~css
div:hover {
animation: 1s 1s rainbow linear 3 forwards normal;
}
~~~
~~~css
div:hover {
animation-name: rainbow;
animation-duration: 1s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode:forwards;
animation-direction: normal;
animation-iteration-count: 3; //重復次數
}
~~~
5. **keyframes的寫法**
keyframes關鍵字用來定義動畫的各個狀態,它的寫法相當自由。
~~~css
@keyframes rainbow {
0% { background: #c00 }
50% { background: orange }
100% { background: yellowgreen }
}
~~~
~~~css
// 0% 可以用from代表,100%可以用to代表
@keyframes rainbow {
from { background: #c00 }
50% { background: orange }
to { background: yellowgreen }
}
~~~
如果省略某個狀態,瀏覽器會自動推算中間狀態,所以下面都是合法的寫法。
~~~css
@keyframes rainbow {
50% { background: orange }
to { background: yellowgreen }
}
@keyframes rainbow {
to { background: yellowgreen }
}
~~~
甚至,可以把多個狀態寫在一行。
~~~css
@keyframes pound {
from,to { transform: none; }
50% { transform: scale(1.2); }
}
~~~
另外一點需要注意的是,瀏覽器從一個狀態向另一個狀態過渡,是平滑過渡。steps函數可以實現分步過渡。
~~~css
div:hover {
animation: 1s rainbow infinite steps(10);
}
~~~
這里有一個非常神奇的[例子](http://dabblet.com/gist/1745856),可以看到steps函數的用處。
6. **animation-play-state**
有時,動畫播放過程中,會突然停止。這時,默認行為是跳回到動畫的開始狀態。
如果想讓動畫保持突然終止時的狀態,就要使用```animation-play-state```屬性。
~~~css
div {
animation: spin 1s linear infinite;
animation-play-state: paused;
}
div:hover {
animation-play-state: running;
}
//上面的代碼指定,沒有鼠標沒有懸停時,動畫狀態是暫停;一旦懸停,動畫狀態改為繼續播放。效果如下。
~~~
7. **瀏覽器前綴**
目前,IE 10和Firefox(>= 16)支持沒有前綴的animation,而chrome不支持,所以必須使用webkit前綴。
也就是說,實際運用中,代碼必須寫成下面的樣子。
~~~css
div:hover {
-webkit-animation: 1s rainbow;
animation: 1s rainbow;
}
@-webkit-keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
@keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
~~~