CSS動畫攻略

2018-06-07 16:57 更新

在網(wǎng)頁設(shè)計中給適當?shù)脑靥砑觿赢嫿换o疑是一個大幅度提升用戶體驗的措施??v觀整個Web開發(fā)的發(fā)展歷史,從最早的原始階段(都是靜態(tài)頁面),到如今這樣一個非常講究用戶體驗的時代,人們越來越在意頁面的表現(xiàn)能力(用戶體驗),干巴巴的展現(xiàn)內(nèi)容往往是沒有什么競爭力的。

就前端開發(fā)這個層面來說,實現(xiàn)動畫的途徑有好幾種。簡單來說可能包括下面幾種方式,

  1. 使用flash
  2. 使用javascript不停的改變dom元素(包括一些第三內(nèi)庫,比如jquery等)
  3. 使用css修飾dom元素

在過去的幾年內(nèi),人們大都在使用第一種或者第二種方法來實現(xiàn)頁面動畫?,F(xiàn)在看來前兩種方法的確很low(第一種方法過重,第二種方法過于繁瑣)。

CSS3的transform(變換),transition(過渡),animation(動畫)三個屬性為純CSS實現(xiàn)動畫提供了有力的支持。本篇文章我們將會詳細的闡述各個屬性的一般性用法,其中將會穿插部分示例。

Transform(變換)

CSS3新增了屬性transform,意為變換。那么,什么叫做變換?簡單的來說就是改變元素的大小、位置、形狀等屬性的操作。

??注意:其實transform還可以分為2D變換3D變換。前者表示在二維空間進行變換操作(即只有X軸和Y軸),而后者表示在三維空間進行變換操作(即除了二維的X軸和Y軸之外還有一個Z軸)。本篇文章僅對2D變換做闡述,3D變換的相關(guān)內(nèi)容后面會專門作文。

W3C中規(guī)定transform包含如下幾種操作類型(這里所有的變換都是在2D變換的范疇內(nèi)),

  • translate 位移
  • rotate 旋轉(zhuǎn)
  • scale 縮放
  • skew 傾斜
  • matrix 變換矩陣

一般來說,transform的語法如下,


transform: none | <transform-function> [ <transform-function>]*
  1. none為默認值,意為不作任何變換
  2. <transform-function>即為上述提到的各種變換操作
  3. 我們可以同時對一個元素進行多重變換操作,即可以賦值多個<transform-function>
  4. 當進行多重變換操作時,不同的變換操作之間使用空格分割而不是采用一貫的,,切記。

transform-origin屬性

在介紹各種變換操作之前,我覺得很有必要先介紹一下transform-origin屬性。此屬性不屬于transform的操作類型,它和transform屬于同一個level的css屬性,它的作用是用于設(shè)置變換操作的原點。

其語法如下,


transform-origin: [<percentage> | <length> | left | center | right] [<percentage> | <length> | top | center | bottom]?
  1. 默認值為center center50% 50%),默認變換原點為元素的中心點。
  2. 此屬性接收1-2組值,分別應(yīng)用于X軸與Y軸。如果只設(shè)置第一組值,則第二組值將自動采用默認值。
  3. 當參數(shù)值為<percentage> | <length>時,可以為負值。

記住,所有的二維變換操作都必須基于一個原點,默認的原點為元素的中心點。

此參數(shù)的瀏覽器兼容性如下,

部分支持的瀏覽器需要我們在實際使用時添加各個瀏覽器的私有前綴。

下面我們來看一個例子見識一下改變transform-origin后的變換效果,


.demo {
    transform-origin: 100% 0;
    transform: rotate(45deg);
}

效果如下,

圖中左側(cè)的效果應(yīng)用了transform-origin: 100% 0;導(dǎo)致其旋轉(zhuǎn)變換原點轉(zhuǎn)移到了右上角??捎谟覀?cè)未設(shè)置變換原點的效果圖進行對比體會其變化。

translate

translate意為位移。它的一般性用法如下,


.demo {
    transform: translate(50px, 50px);
}

上面的代碼表示將.demo元素以其變換原點(元素中心點)為基準,各向右(X軸)和向下(Y軸)移動50px。其效果如下圖,

注意:從上圖的效果中,我們可以看出translate其實是通過將元素的中心點移動到新的位置來使得整個元素達到位移目的的。

translate(50px, 50px)是位移操作最基本的用法,其還有如下幾種變形,

  • translate(50px),省略第二個參數(shù),此時只進行X軸位移,Y軸位移量默認為0。
  • translate(0, 50px),可以顯式的聲明X軸位移量為0,這樣僅進行Y軸位移。
  • translateX(50px),等同于translate(50px, 0),只進行X軸位移。
  • translateY(50px),等同于translate(0, 50px),只進行Y軸位移。

rotate

rotate意為旋轉(zhuǎn)。它的一般性用法如下,


.demo {
    transform: rotate(45deg);
}

上面代碼表示將.demo元素以其變換原點(元素中心點)為基準,順時針旋轉(zhuǎn)45度。效果如下,

  • rotate(45deg),接收一個參數(shù),此參數(shù)表示旋轉(zhuǎn)的度數(shù)。
  • rotate的參數(shù)可以傳入一個正值,亦可以傳入一個負值(比如-45deg)。正值表示旋轉(zhuǎn)方向為順時針,負值表示旋轉(zhuǎn)方向為逆時針。

scale

scale意為縮放。它的一般性用法如下,


.demo {
    transform: scale(1.5);
}

上面的代碼表示將.demo元素以其變換原點(元素中心點)為基準,沿著X軸和Y軸放大1.5倍。效果如下,

scale操作與translate很相似,scale(1.5)是其最基本的用法,除此之外它還有如下幾種變形,

  • scale(1.5, 1.5),可以接收兩個參數(shù),分別表示X軸方向與Y軸方向的縮放。其中第二個參數(shù)可以省略。若省略第二個參數(shù),則第二個參數(shù)與第一個參數(shù)一致。
  • 傳入的參數(shù)如果是<1的值則按比例縮小,若是>1的值則按比例放大。不可傳入負值。
  • 可以使用scaleX()或者scaleY()進行僅對X軸方向或者Y軸方向進行縮放。

skew

skew意為傾斜。它的一般性用法如下,


.demo {
    transform: skew(30deg, 30deg);
}

上面的代碼表示將.demo元素以其變換原點(元素中心點)為基準,沿著X軸順時針傾斜30度,沿著Y軸順時針傾斜30度。效果如下,

注意skew在二維變換中是唯一一個可以使元素發(fā)生形變的操作。

  • skew與之前的translatescale也是類似的,接收2個參數(shù)。其中第二個參數(shù)可以省略,若省略第二個參數(shù),則第二個參數(shù)將自動使用默認值0deg。
  • 可以使用skewX()skewY()進行X軸方向或者Y軸方向的傾斜。
  • 參數(shù)可以設(shè)置為正值亦可以設(shè)置為負值。其中正值表示順時針方向,負值表示逆時針方向。

matrix

關(guān)于matrix的詳細用法,我這里不想多作闡述。因為這種用法基本很少用到,而且還涉及到一些行列式變換的運算。就是說了我估計我也說不清楚。這里只要知道matrix是合并了所有的變化操作就行,如果實在有興趣,可自行查閱相關(guān)文檔。

其實,transform允許對同一元素同時進行多個變換操作,這樣完全可以替代matrix的用法,而且可讀性更佳。

transform總結(jié)

看到這里,可能會一些看官有個疑問,貌似transform并不能實現(xiàn)動畫???

沒錯!

僅僅使用transform是無法實現(xiàn)動畫效果的。因為transform只是對元素進行生硬的變化,這個變化是瞬間的,所以并沒有展現(xiàn)一種持續(xù)變化的效果。

一般地,我們可以將其與下面即將說道的transition搭配使用來得到各種動畫效果。

不過,在適當?shù)臅r候使用transform可以大大簡化頁面實現(xiàn)復(fù)雜度,比如有一個比較復(fù)雜的展示元素,我們現(xiàn)在需要一個與之水平對稱的展示,那么此時只需要rotate即可。

上面所有效果可以在這個demo中進行試驗。

Transition(過渡)

W3C中css3-transition的文檔對transition的定義是這樣的,

CSS Transitions allows property changes in CSS values to occur smoothly over a specified duration.

意思就是:允許css的屬性值在一定的時間區(qū)間內(nèi)平滑地過渡。這種效果可以在鼠標單擊、獲得焦點、被點擊或?qū)υ厝魏胃淖冎杏|發(fā),并圓滑地以動畫效果改變CSS的屬性值。

簡單來說,transition的含義就是元素某一css屬性的過渡。

下面讓我們來詳細看看transition這貨到底是怎么用的。

transition的語法如下,


transition:[ transition-property ] || [ transition-duration ] || [ transition-timing-function ] || [ transition-delay ]

可以看出transition是一個復(fù)合屬性,它包括下面四個子屬性,

  • transition-property,用于設(shè)置需要過渡的css屬性
  • transition-duration,用于設(shè)置過渡的持續(xù)時間
  • transition-timing-function,用于設(shè)置過渡的速率類型(即過渡的動畫類型)
  • transition-delay,用于設(shè)置過渡的開始延時

此外transition允許使用,同時對一個元素進行多個屬性的過渡,比如


.demo {
    transition: width 1s ease-out, height 1s ease-in;
}

這樣我們可以對同一個元素的不同的屬性應(yīng)用不同的過渡策略。

下面我們來分別對每個屬性進行描述,其中可能會穿插一些示例。

transition-property

用于設(shè)置需要過渡的css屬性,語法如下,


transition-property:all | none | <property>[ ,<property> ]*
  • none,不指定過渡的css屬性
  • all,此為默認值,指定所有可進行過渡的css屬性
  • <property>,可自定義需要過渡的css屬性

這里值得一提的是,不是所有的css屬性都是可以進行過渡的。比如display屬性,比如background-image: url(...)(當設(shè)置背景圖片為一個gradient時反而是可以應(yīng)用過渡的),還有一些沒有明確大小的單位,比如height: auto,等等。

這篇文章中有一份可過渡的css屬性列表。列表不但指明了哪些css屬性是可以過渡的,還指明了這些css屬性的取值類型(意思就是,這些css屬性必須滿足這些取值條件才可以應(yīng)用過渡效果)。

這里還有一個demo,展示了幾乎所有的transition效果。

transition-duration

用于設(shè)置過渡的持續(xù)時間,語法如下,


transition-duration:<time>[ ,<time> ]*

這個屬性沒什么可說的,就是用于設(shè)置過渡的持續(xù)時間。過渡時間越短則動畫運行速度越快,過渡時間越長則動畫運行越慢。

此屬性的單位為秒(s),默認值為0。當設(shè)置為0時,則表示過渡是瞬間完成的。

transition-timing-function

用于設(shè)置過渡的速率類型,語法如下,


transition-timing-function:linear | ease | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier

這個屬性相比之前的兩個屬性要稍微復(fù)雜一點,它的設(shè)置非常多樣化。

  • 我們可以使用預(yù)設(shè)的幾種類型:linear(線性過渡),ease(平滑過渡,此為默認值),ease-in(由慢到快),ease-out(由快到慢),ease-in-out(由慢到快再到慢)
  • cubic-bezier(),自定義貝塞爾曲線。其實預(yù)設(shè)的幾種都有對應(yīng)的貝塞爾曲線。
  • steps(<integer>[, [ start | end ] ]?),接受兩個參數(shù)的步進函數(shù)。第一個參數(shù)必須為正整數(shù),指定函數(shù)的步數(shù)。第二個參數(shù)取值可以是start或end,指定每一步的值發(fā)生變化的時間點。第二個參數(shù)是可選的,默認值為end。
  • step-start,等同于steps(1, start)
  • step-end,等同于steps(1, end)

我想這里唯一需要解釋的就是steps相關(guān)的幾種過渡速率類型。steps()的意思就是將整個過渡過程分為特定的步數(shù),并規(guī)定了每一步過渡的執(zhí)行時機。

比如,


transition-property: all;
transition-duration: 2s;
transition-timing-function: steps(5, end);

這段代碼的效果請參見這個demo

steps(5, end)的意思就是,

  1. 將整個持續(xù)2s的過渡過程分為5個步驟。
  2. 每一步的過渡效果將在每一步結(jié)束時發(fā)生(end)。

Lea Verouhttp://cubic-bezier.com/可以可視化定制各種貝塞爾曲線。

MDN上有對每一種過渡速率類型的效果展示。

transition-delay

用于設(shè)置過渡的開始延時,其語法與transition-duration是一樣的。這里就不再贅述了。

不過有一點需要注意,當我們使用transition簡寫模式的時候,一般按照如下的格式來書寫,


.demo {
    transition: all 2s ease 1s;
}

除此之外,你可能還會看到別人這么寫,


.demo {
    transition: 2s 1s
}

僅指明了兩個時間參數(shù),其他的都使用默認參數(shù)。此時第一個時間參數(shù)為transition-duration,第二個時間參數(shù)為transition-delay。

除此之外,我們還可以利用transition-delay屬性來達到一些酷炫的效果,比如


.demo {
    transition: height 1s, width 1s 1s;
}

意思就是先對height屬性進行過渡,延遲1s后對width屬性進行過渡,而這個延遲的時間正好是前一個屬性的過渡時間,從而整體看起來非常平滑。詳情可參閱這個demo。

transition總結(jié)

transition簡單明了,可快速對元素實現(xiàn)一些平滑過渡。不過它也有自己的適用場景和注意事項。

下面是一些使用transition的注意事項,

  1. 由于一些瀏覽器支持原因,在使用transition時最好添加各個瀏覽器廠商的私有前綴,將W3C的語法放在最后。
  2. 不是所有的CSS屬性都支持transition。
  3. transition需要明確知道開始狀態(tài)和結(jié)束狀態(tài)的具體數(shù)值,才能計算出中間狀態(tài)。

transition的局限,

  1. transition必須要外力推動,比如鼠標動作,或者js操作等等,否則無法觸發(fā)過渡。
  2. transition的過渡效果是一次性的,除非人為的反復(fù)觸發(fā)。
  3. transition只能接受兩個邊界狀態(tài)(開始和結(jié)束),中間的過渡狀態(tài)是由瀏覽器自動計算的。無法人為的指定中間狀態(tài)。

為了解決上述問題,CSS Animation應(yīng)用而生了。

Animation(動畫)

animation相比transition制作動畫擁有更高的自定義性,可以定義每一幀的行為。

首先讓我們來看一個模擬月食的demo來體驗一下CSS動畫的魅力。

哈哈,感覺如何,是不是有種很酷炫的感覺。下面讓我們來詳細看看animation的用法吧。

animation的語法如下,


animation: [[ animation-name ] || [ animation-duration ] || [ animation-timing-function ] || [ animation-delay ] || [ animation-iteration-count ] || [ animation-direction ]] [ , [ animation-name ] || [ animation-duration ] || [ animation-timing-function ] || [ animation-delay ] || [ animation-iteration-count ] || [ animation-direction ]]*

transition一樣,我們可以對同一個元素同時應(yīng)用多個animation,比如,


@keyframes typing {
    from { width: 0; }
}
@keyframes blink-caret {
    50% { border-color: transparent; }
}
h1 {
    font: bold 200% Consolas, Monaco, monospace;
    border-right: .1em solid;
    width: 16.5em; /* fallback */
    width: 30ch; /* # of chars */
    margin: 2em 1em;
    white-space: nowrap;
    overflow: hidden;
    animation: typing 20s steps(30, end), blink-caret .5s step-end infinite alternate;
}

上述代碼可以實現(xiàn)一個非常神奇的效果,它給h1元素同時應(yīng)用了typingblink-caret兩種動畫,具體的效果可參見這里

animation可設(shè)置的屬性還是挺多的,下面讓我們一個個的看看每個屬性的具體用法。

animation-name

animation-name意為動畫的名稱。如果不設(shè)置animation-name,那么元素將沒有任何的動畫效果。

其語法如下,


animation-name:none | <identifier> [ , none | <identifier> ]*
  • none,此為默認值,表示不引用任何動畫。
  • <identifier>,引用由@keyframes定義的動畫名稱。

說到這個animation-name屬性,那就不得不說一下@keyframes的相關(guān)知識。

@keyframes

@keyframes用于定義動畫的各個狀態(tài),我們一般稱之為關(guān)鍵幀。其寫法非常自由。其一般的寫法如下,


@keyframes rainbow {
    0% { background: #c00 }
    50% { background: orange }
    100% { background: yellowgreen }
}
  • rainbow即為動畫關(guān)鍵幀的名字,被animation引用。
  • 內(nèi)部可以使用0%~100%自定義動畫的各個狀態(tài)。其中0%表示初始狀態(tài),100%表示結(jié)束狀態(tài)。
  • 還可以用from來代替0%表示初始狀態(tài),可以用to關(guān)鍵字來代替100%表示結(jié)束狀態(tài)。
  • 未明確的狀態(tài)將由瀏覽器自動計算,且不同狀態(tài)之間是平滑過渡的(究竟如何過渡,取決animation-timing-function屬性)。
  • 還可以將多個狀態(tài)寫在一起表示這幾個狀態(tài)是一樣的,比如


@keyframes moonline {
    0% {
        top:220px;
        left:30%;
        opacity:0;
    }
    30%, 50%, 80% {
        top:100px;
        left:50%;
        opacity:1;
    }
    100% {
        top:220px;
        left:80%;
        opacity:0;
    }
}

animation-duration

animation-duration意為動畫持續(xù)時間,跟之前的transition-duration的含義一致。

其語法如下,


animation-duration:<time> [ , <time> ]*
  • 設(shè)置動畫的持續(xù)時間,單位為秒(s),其默認值為0。

animation-timing-function

animation-timing-function用于設(shè)置動畫的速率類型。這個屬性與transition-timing-function基本一致。

其語法如下,


transition-timing-function:linear | ease | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier

具體的解釋這里就不再贅述了,可參考transition-timing-function。

animation-delay

animation-delay用于設(shè)置動畫開始的延時。此屬性與transition-delay基本一致,請參考transition-delay的相關(guān)說明。

animation-iteration-count

此屬性用于設(shè)置動畫的循環(huán)次數(shù)。其語法如下,


animation-iteration-count:infinite | <number> [ , infinite | <number> ]*
  • 此參數(shù)可以設(shè)置為一個<integer>,明確標示動畫的循環(huán)次數(shù)。默認值為1,即動畫只運行一次。
  • 還可接收關(guān)鍵字infinite,表示動畫將運行無限次。

animation-direction

簡單來說,此屬性用于設(shè)置動畫在循環(huán)運行過程中是否允許反向運動。這啥意思呢?

我們知道當動畫循環(huán)運行時,一次運行周期為:從初始狀態(tài)到結(jié)束狀態(tài)的平滑過渡。一次運行周期結(jié)束后,元素再次下一個周期,即又從初始狀態(tài)平滑過渡到結(jié)束狀態(tài)。我們可以利用animation-direction屬性改變動畫運行偶數(shù)周期的行為。

此參數(shù)的語法如下,


animation-direction:normal | alternate | reverse | alternate-reverse
  • normal,表示使用默認的行為,不作任何改變。
  • alternate,允許動畫在偶數(shù)周期期間,讓元素從結(jié)束狀態(tài)平滑過渡到初始狀態(tài)。
  • reverse,動畫的所有運行周期中,讓元素從結(jié)束狀態(tài)平滑過渡到初始狀態(tài)。
  • alternate-reverse,動畫的奇數(shù)周期內(nèi)過渡方向與設(shè)置的方向相反,偶數(shù)周期內(nèi)過渡方向與設(shè)置的方向相同。

這四個預(yù)定義值,一般比較常用的是normalalternate。下面是一個例子,


@keyframes rainbow {
    0% {
        background-color: yellow;
    }
    100% {
        background: blue;
    }
}
.demo:hover {
  animation: 1s rainbow 3 normal;
}
.demo2:hover {
  animation: 1s rainbow 3 alternate;
}
.demo3:hover {
  animation: 1s rainbow 3 reverse;
}
.demo4:hover {
  animation: 1s rainbow 3 alternate-reverse;
}

其效果如下,

本demo來自CSS動畫簡介。

animation-play-state

語法如下,


animation-play-state:running | paused [, running | paused]*
  • 此屬性用于控制動畫的運行狀態(tài)。
  • 有兩個可選值,running(運動狀態(tài))和paused(暫停狀態(tài))。其中running為默認值。
  • 當某個動畫從暫停狀態(tài)->運動狀態(tài)時,它并不會重新從初始狀態(tài)開始,而是在上次暫停的狀態(tài)繼續(xù)運行動畫。

下面讓我們來看一個例子。


div {
trueanimation: spin 2s linear infinite;
trueanimation-play-state: paused;
}
div:hover {
    animation-play-state: running;
}
@keyframes spin {
    from {
        transform: rotate(0deg);
true}
trueto {
true    transform: rotate(360deg);
true}
}

具體的效果請參見這個demo

animation-fill-mode

此屬性用于設(shè)置動畫時間之外元素的狀態(tài)。這里的動畫時間之外可能包括動畫開始運行之前、動畫結(jié)束運行之后、動畫暫停運行時。

其語法如下,


animation-fill-mode:none | forwards | backwards | both
  • none,此為默認值,意為不設(shè)置動畫之外的狀態(tài)。
  • forwards,設(shè)置狀態(tài)為動畫結(jié)束時的狀態(tài)。
  • backwards,設(shè)置狀態(tài)為動畫開始時的狀態(tài)。
  • both,設(shè)置狀態(tài)為動畫結(jié)束或開始的狀態(tài)。當循環(huán)運行動畫時,both會更具根據(jù)animation-direction輪流應(yīng)用forwardsbackwards規(guī)則。

詳情可參考這個demo。

animation總結(jié)

其實animation可以說是transition的進階版本。transition針對元素的某一個(或者某幾個)特定的css屬性進行過渡,而animation可以針對元素在過渡期間自定義任意一幀的狀態(tài)。如果不考慮低版本瀏覽器的兼容性,使用css動畫來提升用戶體驗是一種非常好得方式,

個人感覺,從某種意義上來說,設(shè)計師是決定用戶體驗的第一道門檻,CSS的相關(guān)內(nèi)容都是實現(xiàn)。在實際的工作中,我們可以發(fā)揮自己的想象力,使用css動畫的相關(guān)知識,組合各種效果。

參考列表


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號