當(dāng)前位置:首頁(yè) > IT技術(shù) > Web編程 > 正文

CSS交互動(dòng)畫(huà)指南之keyframes
2021-09-24 14:52:02

CSS交互動(dòng)畫(huà)指南之keyframes_css

過(guò)去 WEB 需要實(shí)現(xiàn)交互動(dòng)畫(huà)效果是使用 ??flash?? 、??javascript??、??Gif??,近年來(lái)隨著 ??flash?? 的淘汰,??javascript?? 和 ??CSS?? 功能的增強(qiáng),使得現(xiàn)代 WEB 應(yīng)用的交互越來(lái)越豐富。借此總結(jié)一下 CSS 交互動(dòng)畫(huà)實(shí)現(xiàn)的基礎(chǔ),關(guān)鍵的知識(shí)點(diǎn)是 ??keyframes?? ,文章涉及的代碼示例效果可以點(diǎn)擊查看????動(dòng)畫(huà)效果。

語(yǔ)法

??keyframe?? 動(dòng)畫(huà)的實(shí)現(xiàn)原理跟 ??flash?? 的實(shí)現(xiàn)方式類(lèi)似,在 CSS 塊之間進(jìn)行關(guān)鍵幀的屬性的更新。下面定義一個(gè) ??keyframe?? 動(dòng)畫(huà),將元素的水平位置從 ??-100%?? 平滑地漸變到??0%??:

@keyframes slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0%);
}
}


每個(gè) ??@keyframes?? 語(yǔ)句都需要一個(gè)名稱(chēng),一般為交互動(dòng)畫(huà)效果名稱(chēng),上面的代碼定了一個(gè)滑入 ??slide-in?? 的效果名稱(chēng)。

和其它 CSS 一樣,??keyframe?? 動(dòng)畫(huà)也是可以通用的和可重用的,可以將它們應(yīng)用到特定選擇器的 ??animation?? 屬性中:

.slide-in {
animation: slide-in 1000ms;
}

上面的代碼定了在 ??1000ms?? 內(nèi),將 ??translateX?? 屬性進(jìn)行改變,并且立即執(zhí)行。

可以在同一個(gè)動(dòng)畫(huà)聲明中定義多個(gè)屬性的變化,如下:

.drop-in {
animation: drop-in 1000ms;
}
@keyframes drop-in {
from {
transform: rotate(-30deg) translateY(-100%);
opacity: 0;
}
to {
transform: rotate(0deg) translateY(0%);
opacity: 1;
}
}

動(dòng)畫(huà)效果

動(dòng)畫(huà)效果使用 ??animation-timing-function?? 屬性,定義 CSS 動(dòng)畫(huà)在每一動(dòng)畫(huà)周期中執(zhí)行的節(jié)奏,既是常說(shuō)的動(dòng)畫(huà)效果,類(lèi)似 ??jquery?? 中的 ??easing?? 。

.ease-in-out {
animation-timing-function: ease-in-out;
}

循環(huán)動(dòng)畫(huà)

默認(rèn)情況下,??keyframe?? 動(dòng)畫(huà)只會(huì)運(yùn)行一次,但可以使用 ??animation-iteration-count?? 屬性來(lái)控制動(dòng)畫(huà)執(zhí)行次數(shù)。

.for-three {
animation-iteration-count: 3;
}

如果是無(wú)限次將其值設(shè)置為 ??infinite?? ,有限次就按照具體要求輸入次數(shù)。

.spinner {
animation: spin 1000ms;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes spin {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}

多步動(dòng)畫(huà)

除了 ??from?? 和 ??to?? 關(guān)鍵字,還可以使用百分比,可以定義兩個(gè)及以上的動(dòng)畫(huà)步驟:

.fancy-spinner {
animation: fancy-spin 2000ms;
animation-iteration-count: infinite;
}
@keyframes fancy-spin {
0% {
transform: rotate(0turn) scale(1);
}
25% {
transform: rotate(1turn) scale(1);
}
50% {
transform: rotate(1turn) scale(0.5);
}
75% {
transform: rotate(0turn) scale(0.5);
}
100% {
transform: rotate(0turn) scale(1);
}
}

交替動(dòng)畫(huà)

假設(shè)要讓一個(gè)元素“呼吸”,充氣和放氣。 可以將其設(shè)置為 3 步動(dòng)畫(huà):

.grow-shrink {
animation: grow-and-shrink 4000ms;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
@keyframes grow-and-shrink {
0% {
transform: scale(1);
}
50% {
transform: scale(0.5);
}
100% {
transform: scale(1);
}
}

上面的動(dòng)畫(huà)效果還有一種更優(yōu)雅的方式,使用 ??animation-direction?? 屬性,用來(lái)指示動(dòng)畫(huà)是否反向播放。

@keyframes grow-and-shrink {
0% {
transform: scale(1);
}
100% {
transform: scale(0.5);
}
}

.grow-shrink {
animation: grow-and-shrink 2000ms;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-direction: alternate;
}

上面定義的動(dòng)畫(huà)都是根據(jù)不同屬性定義不同的值,和其他 CSS 屬性一樣,可以只定義一個(gè)屬性值,即 ??animation??。

上面定義動(dòng)畫(huà)屬性的方式如下:

animation: grow-and-shrink 2000ms;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-direction: alternate;

更簡(jiǎn)潔的方式,也是推薦使用的方式,跟 ??padding?? 不一樣的是順序無(wú)關(guān)緊要:

animation: grow-and-shrink 2000ms ease-in-out infinite alternate;

填充模式

??keyframe?? 動(dòng)畫(huà)令人困惑的方面可能是填充模式,它們是通往??keyframe?? 信心之路的最大障礙。例如希望元素淡出,動(dòng)畫(huà)本身運(yùn)行良好,但是當(dāng)它結(jié)束時(shí),元素會(huì)重新出現(xiàn)一下導(dǎo)致閃現(xiàn)的效果:

.fade-out {
animation: fade-out 1000ms;
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}

為什么元素會(huì)執(zhí)行完動(dòng)畫(huà)后重新再閃現(xiàn)一下并完全可見(jiàn)了,這是因?yàn)???from?? 和 ??to?? 塊中的聲明只在動(dòng)畫(huà)運(yùn)行時(shí)有效。

??1000ms?? 動(dòng)畫(huà)完成過(guò)后,元素就按照CSS聲明顯示,而透明度默認(rèn)情況下是不透明的。因此動(dòng)畫(huà)完成后透明度又恢復(fù)到不透明了。

解決這個(gè)問(wèn)題的一種方法是在動(dòng)畫(huà)之外聲明透明度,如下:

.fade-out-2 {
animation: fade-out 1000ms;
opacity: 0;
}

上面的方案雖然解決了問(wèn)題,但這不是最佳的方式。最佳的方式是使用屬性 ??animation-fill-mode?? ,設(shè)置CSS動(dòng)畫(huà)在執(zhí)行之前和之后如何將樣式應(yīng)用于其目標(biāo)。

.fade-out-forwards {
animation: fade-out 1000ms;
animation-fill-mode: forwards;
}

??animation-fill-mode?? 屬性的參數(shù)有以下四個(gè):

??none?? :這是默認(rèn)值,當(dāng)動(dòng)畫(huà)未執(zhí)行時(shí),動(dòng)畫(huà)將不會(huì)將任何樣式應(yīng)用于目標(biāo),而是已經(jīng)賦予給該元素的 CSS 規(guī)則來(lái)顯示該元素; ??forwards??:目標(biāo)將保留由執(zhí)行期間遇到的最后一個(gè)關(guān)鍵幀計(jì)算值,最后一個(gè)關(guān)鍵幀取決于??animation-direction??和??animation-iteration-count??的值; ??backwards??:動(dòng)畫(huà)將在應(yīng)用于目標(biāo)時(shí)立即應(yīng)用第一個(gè)關(guān)鍵幀中定義的值,并在??animation-delay??期間保留此值。 第一個(gè)關(guān)鍵幀取決于??animation-direction??的值; ??both??:動(dòng)畫(huà)將遵循 ??forwards?? 和 ??backwards?? 的規(guī)則,從而在兩個(gè)方向上擴(kuò)展動(dòng)畫(huà)屬性。

動(dòng)態(tài)動(dòng)畫(huà)

??keyframe?? 動(dòng)畫(huà)實(shí)現(xiàn)了基本的動(dòng)畫(huà)效果,將它們與CSS變量一起使用的時(shí)候可以定義更加復(fù)雜的效果。

.bounce-box {
animation: bounce 300ms alternate infinite cubic-bezier(0.2, 0.65, 0.6, 1);
}
@keyframes bounce {
from {
transform: translateY(0px);
}
to {
transform: translateY(62px);
}
}

CSS動(dòng)畫(huà)是可以通用的和可重用的,但是這個(gè)動(dòng)畫(huà)總是會(huì)讓一個(gè)元素彈跳 62px。如果不同的元素可以提供不同的“彈跳高度”,就提高了動(dòng)畫(huà)的靈活性。

使用CSS變量,就可以做到:

@keyframes bounceY {
from {
transform: translateY(0px);
}
to {
transform: translateY(var(--bounce-offset));
}
}

.bounceY-box {
float: left;
animation: bounce alternate infinite cubic-bezier(0.2, 0.65, 0.6, 1);
}
.bounceY-box.one {
--bounce-offset: 62px;
animation-duration: 200ms;
}
.bounceY-box.two {
--bounce-offset: 32px;
animation-duration: 300ms;
}
.bounceY-box.three {
--bounce-offset: -40px;
animation-duration: 400ms;
}

總結(jié)

CSS 在近幾年發(fā)生了多大的變化,功能變得越來(lái)越強(qiáng)大,促進(jìn)未來(lái) WEB 應(yīng)用變得更佳豐富。

本文摘自 :https://blog.51cto.com/u

開(kāi)通會(huì)員,享受整站包年服務(wù)立即開(kāi)通 >