W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
CSS 動(dòng)畫可以在不借助 Javascript 的情況下做出一些簡(jiǎn)單的動(dòng)畫效果。
你也可以通過(guò) Javascript 控制 CSS 動(dòng)畫,使用少量的代碼,就能讓動(dòng)畫表現(xiàn)更加出色。
CSS 過(guò)渡的理念非常簡(jiǎn)單,我們只需要定義某一個(gè)屬性以及如何動(dòng)態(tài)地表現(xiàn)其變化。當(dāng)屬性變化時(shí),瀏覽器將會(huì)繪制出相應(yīng)的過(guò)渡動(dòng)畫。
也就是說(shuō):我們只需要改變某個(gè)屬性,然后所有流暢的動(dòng)畫都由瀏覽器生成。
舉個(gè)例子,以下 CSS 會(huì)為 backgroud-color
的變化生成一個(gè) 3 秒的過(guò)渡動(dòng)畫:
.animated {
transition-property: background-color;
transition-duration: 3s;
}
現(xiàn)在,只要一個(gè)元素?fù)碛忻麨?nbsp;.animated
的類,那么任何背景顏色的變化都會(huì)被渲染為 3 秒鐘的動(dòng)畫。
單擊以下按鈕以演示動(dòng)畫:
<button id="color">Click me</button>
<style>
#color {
transition-property: background-color;
transition-duration: 3s;
}
</style>
<script>
color.onclick = function() {
this.style.backgroundColor = 'red';
};
</script>
CSS 提供了四個(gè)屬性來(lái)描述一個(gè)過(guò)渡:
transition-property
?transition-duration
?transition-timing-function
?transition-delay
?之后我們會(huì)詳細(xì)介紹它們,目前我們需要知道,我們可以在 transition
中以 property duration timing-function delay
的順序一次性定義它們,并且可以同時(shí)為多個(gè)屬性設(shè)置過(guò)渡動(dòng)畫。
請(qǐng)看以下例子,點(diǎn)擊按鈕生成 color
和 font-size
的過(guò)渡動(dòng)畫:
<button id="growing">Click me</button>
<style>
#growing {
transition: font-size 3s, color 2s;
}
</style>
<script>
growing.onclick = function() {
this.style.fontSize = '36px';
this.style.color = 'red';
};
</script>
現(xiàn)在讓我們一個(gè)一個(gè)展開(kāi)看這些屬性。
在 transition-property
中我們可以列舉要設(shè)置動(dòng)畫的所有屬性,如:left、margin-left、height 和 color
。
不是所有的 CSS 屬性都可以使用過(guò)渡動(dòng)畫,但是它們中的大多數(shù)都是可以的。all
表示應(yīng)用在所有屬性上。
transition-duration
允許我們指定動(dòng)畫持續(xù)的時(shí)間。時(shí)間的格式參照 CSS 時(shí)間格式:?jiǎn)挝粸槊?nbsp;s
或者毫秒 ms
。
transition-delay
允許我們?cè)O(shè)定動(dòng)畫開(kāi)始前的延遲時(shí)間。例如,對(duì)于 transition-delay: 1s
,動(dòng)畫將會(huì)在屬性變化發(fā)生 1 秒后開(kāi)始渲染。
你也可以提供一個(gè)負(fù)值。那么動(dòng)畫將會(huì)從整個(gè)過(guò)渡的中間時(shí)刻開(kāi)始渲染。例如,對(duì)于 transition-duration: 2s
,同時(shí)把 delay
設(shè)置為 -1s
,那么這個(gè)動(dòng)畫將會(huì)持續(xù) 1 秒鐘,并且從正中間開(kāi)始渲染。
這里演示了數(shù)字從 0
到 9
的動(dòng)畫,使用了 CSS translate
方法:
如下在 tranform
屬性上應(yīng)用動(dòng)畫:
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
}
在以上的例子中,JavaScript 把 .animate
類添加到了元素上,由此觸發(fā)了動(dòng)畫:
stripe.classList.add('animate');
我們也可以『從中間』開(kāi)始,也就是說(shuō)從某個(gè)特定數(shù)字開(kāi)始,比方說(shuō),從當(dāng)前的時(shí)間的秒數(shù)開(kāi)始。這就要用到負(fù)的 transition-delay
。
此處,如果你單擊這個(gè)數(shù)字,那么它會(huì)從當(dāng)前的秒數(shù)開(kāi)始渲染:
只需添加一行 JavaScript 代碼:
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
// for instance, -3s here starts the animation from the 3rd second
stripe.style.transitionDelay = '-' + sec + 's';
stripe.classList.add('animate');
};
時(shí)間函數(shù)描述了動(dòng)畫進(jìn)程在時(shí)間上的分布。它是先慢后快還是先快后慢?
乍一看,這可能是最復(fù)雜的屬性了,但是稍微花點(diǎn)時(shí)間,你就會(huì)發(fā)現(xiàn)其實(shí)也很簡(jiǎn)單。
這個(gè)屬性接受兩種值:一個(gè)貝塞爾曲線(Bezier curve)或者階躍函數(shù)(steps)。我們先從貝塞爾曲線開(kāi)始,這也是較為常用的。
時(shí)間函數(shù)可以用貝塞爾曲線描述,通過(guò)設(shè)置四個(gè)滿足以下條件的控制點(diǎn):
(0,0)
?。(1,1)
?。x
? 必須位于 ?0..1
? 之間,?y
? 可以為任意值。CSS 中設(shè)置一貝塞爾曲線的語(yǔ)法為:cubic-bezier(x2, y2, x3, y3)
。這里我們只需要設(shè)置第二個(gè)和第三個(gè)值,因?yàn)榈谝粋€(gè)點(diǎn)固定為 (0,0)
,第四個(gè)點(diǎn)固定為 (1,1)
。
時(shí)間函數(shù)描述了動(dòng)畫進(jìn)行的快慢。
x
? 軸表示時(shí)間:?0
? —— 開(kāi)始時(shí)刻,?1
? —— ?transition-duration
?的結(jié)束時(shí)刻。y
? 軸表示過(guò)程的完成度:?0
? —— 屬性的起始值,?1
? —— 屬性的最終值。最簡(jiǎn)單的一種情況就是動(dòng)畫勻速進(jìn)行,可以通過(guò)設(shè)置曲線為 cubic-bezier(0, 0, 1, 1)
來(lái)實(shí)現(xiàn)。
看上去就像這樣:
…正如我們所見(jiàn),這就是條直線。隨著時(shí)間 x
推移,完成度 y
穩(wěn)步從 0
增長(zhǎng)到 1
。
例子中的列車勻速地從左側(cè)移動(dòng)到右側(cè):
這個(gè)里面的 CSS 就是基于剛才那條曲線的:
.train {
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
/* JavaScript sets left to 450px */
}
…那么,我們?nèi)绻憩F(xiàn)出減速行駛的列車呢?
我們可以使用另一條貝塞爾曲線:cubic-bezier(0.0, 0.5, 0.5 ,1.0)
。
圖像如下:
正如我們所見(jiàn),這個(gè)過(guò)程起初很快:曲線開(kāi)始迅速升高,然后越來(lái)越慢。
這是實(shí)際的效果演示:
CSS:
.train {
left: 0;
transition: left 5s cubic-bezier(0, .5, .5, 1);
/* JavaScript sets left to 450px */
}
CSS 提供幾條內(nèi)建的曲線:linear
、ease
、ease-in
、ease-out
和 ease-in-out
。
linear
其實(shí)就是 cubic-bezier(0, 0, 1, 1)
的簡(jiǎn)寫 —— 一條直線,剛剛我們已經(jīng)看過(guò)了。
其它的名稱是以下貝塞爾曲線的簡(jiǎn)寫:
ease *
|
ease-in
|
ease-out
|
ease-in-out
|
---|---|---|---|
(0.25, 0.1, 0.25, 1.0)
|
(0.42, 0, 1.0, 1.0)
|
(0, 0, 0.58, 1.0)
|
(0.42, 0, 0.58, 1.0)
|
*
—— 默認(rèn)值,如果沒(méi)有指定時(shí)間函數(shù),那么將使用 ease
作為默認(rèn)值。
所以,我們可以使用 ease-out
來(lái)表現(xiàn)減速行駛的列車:
.train {
left: 0;
transition: left 5s ease-out;
/* transition: left 5s cubic-bezier(0, .5, .5, 1); */
}
但是這看起來(lái)有點(diǎn)怪怪的。
貝塞爾曲線可以使動(dòng)畫『超出』其原本的范圍。
曲線上的控制點(diǎn)的 y
值可以使任意的:不管是負(fù)值還是一個(gè)很大的值。如此,貝塞爾曲線就會(huì)變得很低或者很高,讓動(dòng)畫超出其正常的范圍。
在一下的例子中使用的代碼:
.train {
left: 100px;
transition: left 5s cubic-bezier(.5, -1, .5, 2);
/* JavaScript sets left to 400px */
}
left
本該在 100px
到 400px
之間變化。
但是如果你點(diǎn)擊列車,你會(huì)發(fā)現(xiàn):
left
? 會(huì)變得小于 ?100px
?。400px
?。400px
?。為什么會(huì)這樣?看一眼給定的貝塞爾曲線的圖像你就會(huì)明白了。
我們把第二個(gè)點(diǎn)的 y
坐標(biāo)移動(dòng)到了小于 0
的位置,同時(shí)把第三個(gè)點(diǎn)的 y
坐標(biāo)移動(dòng)到了大于 1
的位置,因此曲線已經(jīng)不再像一個(gè)四分之一圓了。y
坐標(biāo)超出了常規(guī)的 0..1
的范圍。
正如我們所知,y
表示『動(dòng)畫進(jìn)程的完成度』。y = 0
表示屬性的初始值,y = 1
則表示屬性的最終值。因此,y < 0
意味著屬性值要比初始值小,而 y > 1
則表明屬性值要比最終值大。
當(dāng)然了,-1
和 2
還是比較緩和的值。如果我們把 y
設(shè)為 -99
和 99
,那么列車將會(huì)偏離地更遠(yuǎn)。
但是,如何針對(duì)特定的任務(wù)尋找到合適的貝塞爾曲線呢?事實(shí)上,有很多工具可以幫到你。比方說(shuō),我們可以利用這個(gè)網(wǎng)站:http://cubic-bezier.com/。
時(shí)間函數(shù) steps(number of steps[, start/end])
允許你讓動(dòng)畫分段進(jìn)行,number of steps
表示需要拆分為多少段。
讓我們通過(guò)一個(gè)數(shù)字的例子來(lái)演示一下。我們將會(huì)讓數(shù)字以離散的方式變化,而不是以連續(xù)的方式。
為了達(dá)到效果,我們把動(dòng)畫拆分為 9 段:
#stripe.animate {
transform: translate(-90%);
transition: transform 9s steps(9, start);
}
step(9, start)
生效時(shí):
steps
的第一個(gè)參數(shù)表示段數(shù)。這個(gè)過(guò)渡動(dòng)畫將會(huì)被拆分為 9 個(gè)部分(每個(gè)占 10%)。時(shí)間間隔也會(huì)以同樣的方式被拆分:9 秒會(huì)被分割為多個(gè)時(shí)長(zhǎng) 1 秒的間隔。
第二個(gè)參數(shù)可以取 start
或 end
兩者其一。
start
表示在動(dòng)畫開(kāi)始時(shí),我們需要立即開(kāi)始第一段的動(dòng)畫。
可以觀察到,在動(dòng)畫過(guò)程中:當(dāng)我們單擊數(shù)字之后,它會(huì)立馬變?yōu)?nbsp;1
(即第一段),然后在下一秒開(kāi)始的時(shí)候繼續(xù)變化。
具體的流程如下:
0s
? —— ?-10%
?(在第一秒開(kāi)始的時(shí)候立即變化)1s
? —— ?-20%
?8s
? – ?-80%
?另一個(gè)值 end
表示:改變不應(yīng)該在最開(kāi)始的時(shí)候發(fā)生,而是發(fā)生在每一段的最后時(shí)刻。
其流程如下:
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: