頁動(dòng)畫圖像、Flash 動(dòng)畫和 JavaScript 實(shí)現(xiàn)的效果圖片,我們用最基礎(chǔ)的CSS也能實(shí)現(xiàn)。制作一個(gè)簡單的gif動(dòng)畫圖,上圖就是效果圖。
用CSS3制作動(dòng)畫圖,你需要了解兩個(gè)css屬性。
因?yàn)?strong>它限定了CSS 樣式和動(dòng)畫逐步從目前的樣式更改為新的樣式的變化過程。瀏覽器兼容的時(shí)候需要在keyframes上加前綴,-webkit-, -ms- 或 -moz- 。
keyframes中有兩個(gè)屬性,from和to,from里面的內(nèi)容定義動(dòng)畫開始的狀態(tài),to記錄動(dòng)畫結(jié)束的狀態(tài)。@keyframes后面緊跟的是動(dòng)畫的名字,這個(gè)可以自定義取名字,比如我取 gifname,頁面某個(gè)標(biāo)簽元素使用這個(gè)動(dòng)畫時(shí)候,就需要用到這個(gè)名字。
@keyframes gifname
{
from {background: red;}
to {background: yellow;}
}
@-webkit-keyframes gifname /* Safari 與 Chrome */
{
from {background: red;}
to {background: yellow;}
}
from和to也可以用百分比來表示動(dòng)畫的過程,可以用百分比的話,就可以把動(dòng)畫的內(nèi)容定義得更加豐富了。
@keyframes gifname
{
0% {background: red;}
25% {background: yellow;}
50% {background: blue;}
100% {background: green;}
}
@-webkit-keyframes gifname /* Safari 與 Chrome */
{
0% {background: red;}
25% {background: yellow;}
50% {background: blue;}
100% {background: green;}
}
比如我在一個(gè)div元素上用到這個(gè)動(dòng)畫
div
{
animation: gifname 5s;
-webkit-animation: gifname 5s; /* Safari 與 Chrome */
}
剛剛我們?cè)赿iv元素中看到的animation就是我們要認(rèn)識(shí)的第二個(gè)屬性。animation其實(shí)是一堆屬性的簡寫。比如看下面一句代碼:
animation:gifname 2s step-start 1s infinite alternate;
這一句其實(shí)可以寫成
animation-name: gifname;
animation-duration: 2s;
animation-timing-function: step-start;
animation-delay: 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-name:動(dòng)畫名稱
這里是 引入 @keyframes 動(dòng)畫的名稱。
animation-duration:動(dòng)畫的持續(xù)時(shí)間
單位可以是秒(s),也可以是毫秒(ms)
animation-timing-function:動(dòng)畫的過度類型
屬性值 :默認(rèn)是 "ease"
linear:線性過渡。等同于貝塞爾曲線(0.0, 0.0, 1.0, 1.0)
ease:平滑過渡。等同于貝塞爾曲線(0.25, 0.1, 0.25, 1.0)
ease-in:由慢到快。等同于貝塞爾曲線(0.42, 0, 1.0, 1.0)
ease-out:由快到慢。等同于貝塞爾曲線(0, 0, 0.58, 1.0)
ease-in-out:由慢到快再到慢。等同于貝塞爾曲線(0.42, 0, 0.58, 1.0)
cubic-bezier(n,n,n,n):在 cubic-bezier 函數(shù)中自己的值。可能的值是從 0 到 1 的數(shù)值。
step-start:馬上跳到動(dòng)畫每一結(jié)束幀的狀態(tài)
animation-delay:動(dòng)畫延遲時(shí)間
默認(rèn)是 0。
animation-iteration-count:動(dòng)畫循環(huán)次數(shù)
默認(rèn)是 1。屬性值infinite 代表無數(shù)次。
animation-direction:動(dòng)畫是否在下一周期逆向地播放
屬性值
normal:正常方向
reverse:反方向運(yùn)行
alternate:動(dòng)畫先正常運(yùn)行再反方向運(yùn)行,并持續(xù)交替運(yùn)行
alternate-reverse:動(dòng)畫先反運(yùn)行再正方向運(yùn)行,并持續(xù)交替運(yùn)行
另外還有兩項(xiàng)屬性:
animation-fill-mode:設(shè)置動(dòng)畫播放后的效果
取值:
none:初始樣式,不改變默認(rèn)行為.(默認(rèn)行為)
forwards:動(dòng)畫播放結(jié)束后保持最后一個(gè)狀態(tài);
backwards:結(jié)束后保持第一個(gè)狀態(tài);
animation-play-state :檢索或設(shè)置對(duì)象動(dòng)畫的狀態(tài)
屬性值
animation-play-state:running | paused;
running:運(yùn)動(dòng)
paused: 暫停
animation-play-state:paused; 當(dāng)鼠標(biāo)經(jīng)過時(shí)動(dòng)畫停止,鼠標(biāo)移開動(dòng)畫繼續(xù)執(zhí)行
到此為止,屬性我們都學(xué)習(xí)完了,開始實(shí)踐部分:
首先準(zhǔn)備好我們需要的圖片,這里我使用了九張圖片。
我把九張圖片放在九個(gè)<li></li>標(biāo)簽里。所有l(wèi)i標(biāo)簽用ul標(biāo)簽包含起來。然后把ul放在一個(gè)div標(biāo)簽里,div設(shè)置成一張圖片的大小,然后通過逐幀移動(dòng)ul元素實(shí)現(xiàn)動(dòng)畫。
最后的處理,把超出div元素的部分隱藏即可。然后就得到了文章開始時(shí)候的圖片了。
最關(guān)鍵的,上代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>css動(dòng)畫</title>
<style>
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
margin-right: 0;
}
#div{
width:100px;
height:100px;
border: 1px solid #fff;
overflow: hidden;
margin: 100px 0 0 100px;
}
#box{
width:900px;
height:100px;
border: 1px solid #fff;
overflow:visible;
position:relative;
animation:myfirst 2s step-start 1s infinite ;
/* Firefox: */
-moz-animation:myfirst 2s step-start 1s infinite ;
/* Safari and Chrome: */
-webkit-animation:myfirst 2s step-start 1s infinite ;
/* Opera: */
-o-animation:myfirst 2s step-start 1s infinite ;
}
#box li{
float: left;
width:98px;
height:100px;
border:1px solid #fff;
}
li img{
width:100%;
height:100%;
}
@keyframes myfirst
{
0% { left:0px; top:0;}
11.1% { left:-100px; top:0;}
22.2% { left:-200px; top:0;}
33.3% { left:-300px; top:0;}
44.4% { left:-400px; top:0;}
55.5% { left:-500px; top:0;}
66.6% { left:-600px; top:0;}
77.7% { left:-700px; top:0;}
88.8% { left:-800px; top:0;}
100% {left:0px; top:0;}
}
@-moz-keyframes myfirst /* Firefox */
{
0% { left:0px; top:0;}
11.1% { left:-100px; top:0;}
22.2% { left:-200px; top:0;}
33.3% { left:-300px; top:0;}
44.4% { left:-400px; top:0;}
55.5% { left:-500px; top:0;}
66.6% { left:-600px; top:0;}
77.7% { left:-700px; top:0;}
88.8% { left:-800px; top:0;}
100% {left:0px; top:0;}
}
@-webkit-keyframes myfirst /* Safari and Chrome */
{
0% { left:0px; top:0;}
11.1% { left:-100px; top:0;}
22.2% { left:-200px; top:0;}
33.3% { left:-300px; top:0;}
44.4% { left:-400px; top:0;}
55.5% { left:-500px; top:0;}
66.6% { left:-600px; top:0;}
77.7% { left:-700px; top:0;}
88.8% { left:-800px; top:0;}
100% {left:0px; top:0;}
}
@-o-keyframes myfirst /* Opera */
{
0% { left:0px; top:0;}
11.1% { left:-100px; top:0;}
22.2% { left:-200px; top:0;}
33.3% { left:-300px; top:0;}
44.4% { left:-400px; top:0;}
55.5% { left:-500px; top:0;}
66.6% { left:-600px; top:0;}
77.7% { left:-700px; top:0;}
88.8% { left:-800px; top:0;}
100% {left:0px; top:0;}
}
</style>
</head>
<body>
<div id="div">
<ul id="box">
<li><img src="./img/o1.jpg"/></li>
<li><img src="./img/o2.jpg"/></li>
<li><img src="./img/o3.jpg"/></li>
<li><img src="./img/o4.jpg"/></li>
<li><img src="./img/o5.jpg"/></li>
<li><img src="./img/o6.jpg"/></li>
<li><img src="./img/o7.jpg"/></li>
<li><img src="./img/o8.jpg"/></li>
<li><img src="./img/o9.jpg"/></li>
</ul>
</div>
</body>
</html>
最后嘮叨一句,該動(dòng)畫不支持IE9及更早版本的IE瀏覽器。
喜歡的話,就點(diǎn)贊支持一下吧!
1.什么是CSS?
2.為什么使用CSS?
3.CSS作用
動(dòng)畫的原理
定義
概念
瀏覽器渲染過程步驟
三棵樹
如何更新樣式
一般JS來更新樣式
三種更新方式
1.JS/CSS》樣式》布局》繪制》合成
全走
比如:div.remove()會(huì)觸發(fā)當(dāng)前消失,其它元素relayout。
2.JS/CSS》樣式》繪制》合成
跳過Layout
比如:改變背景色,直接repaint+composite。
3.JS/CSS》樣式》合成
跳過Layout和Paint
比如:改變transform,直接composite。
CSS動(dòng)畫優(yōu)化
一. transform
四個(gè)常用功能
經(jīng)驗(yàn):
transform: translate
經(jīng)驗(yàn):
#demo{
left:50%;
top:50%;
transform:translate(-50%,-50%);
}
transform: scale
經(jīng)驗(yàn):
transform: rotate
經(jīng)驗(yàn):
transform: skew
經(jīng)驗(yàn):
transform 可以組合使用
transition 過渡
作用
語法
并不是所有的屬性都能過度
二. animation
縮寫語法
使用animation
如何讓動(dòng)畫停在最后一幀
@keyframes 完整語法
本文為作者本人的原創(chuàng)文章,著作權(quán)歸作者本人和饑人谷所有,轉(zhuǎn)載務(wù)必注明來源。
css3的animation想必大家都知道吧,那 steps 逐幀動(dòng)畫你知道嗎?對(duì)于我來說,實(shí)際工作及練習(xí)中也很少用到這種跳躍式變化的動(dòng)畫,而它start和end的解釋又比較“不說人話”,以前用到steps動(dòng)畫的時(shí)候,常常是靠調(diào)試,來回設(shè)置start和end,主打的就是瞎貓碰上死耗子。雖然之前也看過關(guān)于他們區(qū)別的文章,但都是半知半解,過兩天就剩零知零解了。最近忙里偷閑,我終于打算一探究竟了,我倒要看看start和end到底有什么區(qū)別! 順便寫幾個(gè)小demo造福一方~
animation的工作原理是通過將元素的CSS樣式從一個(gè)狀態(tài)改變?yōu)榱硪粋€(gè)狀態(tài)時(shí)(我們稱為線性變化),瀏覽器會(huì)在每個(gè)關(guān)鍵幀之間插入補(bǔ)間動(dòng)畫,所以動(dòng)畫效果是連貫性的,這也就是我們常用的 補(bǔ)間動(dòng)畫。
而steps()逐幀動(dòng)畫則是跳躍式變化,如果說補(bǔ)間動(dòng)畫是一個(gè)滑坡式的變化,那么逐幀動(dòng)畫就是階梯式變化,它的變化沒有中間過程。補(bǔ)間動(dòng)畫就像你看的普通動(dòng)畫片,而逐幀動(dòng)畫就像是那種定格動(dòng)畫。
語法:
animation-timing-function: steps(number, [end | start])
參數(shù)說明:
什么叫在間隔的起點(diǎn)或終點(diǎn)發(fā)生變化呢?光看文字十有八九看不懂,下面就用示例代碼來說明。
上圖是我ps的一張圖,尺寸為200*750,共5個(gè)色塊,每個(gè)色塊高度150。 在示例代碼中我將以這張圖為背景,每一幀將背景上升一個(gè)色塊的高度。關(guān)鍵代碼如下:
animation: ani 5s 2s steps(5,start) infinite backwards;
@keyframes ani{
100%{
background-position:0px -750px;
}
}
在設(shè)置動(dòng)畫前的初始狀態(tài):
再直接來看看動(dòng)畫末態(tài)的情況: 一個(gè)色塊150px,所以動(dòng)畫末態(tài)是背景圖片向上移動(dòng)750px。
為了完整的看到動(dòng)畫效果,我設(shè)置了2秒的動(dòng)畫延遲
我們?cè)O(shè)置的steps的第一個(gè)參數(shù)number為 5 ,也就是把整個(gè)動(dòng)畫過程切割成5個(gè)片段,如下圖:
在實(shí)驗(yàn)之前先來分析一下,既然是片段,那必然有片段的起點(diǎn)和終點(diǎn),可以把補(bǔ)間動(dòng)畫看作點(diǎn),而逐幀動(dòng)畫則是面。那么這五個(gè)片段的起點(diǎn)終點(diǎn)是哪呢,如下圖:
你會(huì)發(fā)現(xiàn),動(dòng)畫是由6個(gè)點(diǎn)切成段五段,帶著這個(gè)思路開始下面的實(shí)驗(yàn)。
先來看一下設(shè)置 start 的效果:
你會(huì)發(fā)現(xiàn)色塊1怎么不顯示了,甚至在動(dòng)畫沒開始前,也就是延時(shí)階段直接就顯示了【2】,變化過程為: 2 - 3 - 4 - 5 - 空
分析一下就可以想到,start是在間隔的起點(diǎn)發(fā)生階越變化,即開始直接就發(fā)生變化了,第一段直接階越到了第一段結(jié)束的位置。
再來看下設(shè)置 end 的效果:
你發(fā)現(xiàn)動(dòng)畫變正常了,動(dòng)畫過程是從【1】到【5】。 再分析一下,因?yàn)閑nd是在間隔終點(diǎn)發(fā)生階越變化,即每一段都會(huì)在其開始階段進(jìn)行停留,這一段結(jié)束后才會(huì)發(fā)生變化直接階越到下一段的開始狀態(tài)。
總結(jié):
可以將補(bǔ)間動(dòng)畫和 steps 逐幀動(dòng)畫類比于點(diǎn)和線的區(qū)別,steps切割開的每個(gè)動(dòng)畫片段就是一條樣式不變的線,而線都有首尾兩個(gè)點(diǎn)。
設(shè)置 start 的 steps 的動(dòng)畫總是在開始發(fā)生變化,即逐幀顯示每一段的終點(diǎn);
而設(shè)置 end 的 steps 的動(dòng)畫總是在結(jié)束發(fā)生變化,即逐幀顯示每一段的起點(diǎn);
其實(shí)很簡單的道理,為什么總是記不住呢,因?yàn)樗腿说膽T性思維恰好相反。設(shè)置start總覺得是顯示每一段的開頭,可它恰好相反,start是開頭發(fā)生變化,顯示的都是每一段的結(jié)尾。
另一種理解思路:
steps(number, [end | start]) 是將動(dòng)畫分為number段,共有number + 1幀畫面。start就是拋棄第一幀畫面執(zhí)行動(dòng)畫,end就是拋棄最后一幀畫面執(zhí)行動(dòng)畫。
注意: 第二個(gè)參數(shù)還有兩個(gè)內(nèi)置值,step-start等同于steps(1,start),動(dòng)畫分成1步,2個(gè)節(jié)點(diǎn),拋棄第一個(gè)節(jié)點(diǎn),即顯示結(jié)尾節(jié)點(diǎn)的狀態(tài);同理step-end等同于steps(1,end)。
jump-start:在每個(gè)時(shí)間間隔開始的時(shí)候跳1步到下一狀態(tài)位置; jump-end:在每個(gè)時(shí)間間隔結(jié)束的時(shí)候跳1步到下一狀態(tài)位置; jump-both:在每個(gè)時(shí)間間隔開始和結(jié)束的時(shí)候跳1步到下一狀態(tài)位置,跳步次數(shù)會(huì)比預(yù)設(shè)的多一次; jump-none:在每個(gè)狀態(tài)位置停留夠一個(gè)時(shí)間間隔才跳到下一位置,跳步次數(shù)會(huì)比與預(yù)設(shè)的少一次
上面我只設(shè)置了動(dòng)畫100%時(shí)的狀態(tài),那如果我設(shè)置了多個(gè)關(guān)鍵幀的狀態(tài)呢,那還是以整個(gè)動(dòng)畫過程切割成number段嗎?
我們?cè)賮碜鰩讉€(gè)實(shí)驗(yàn):
我們將動(dòng)畫時(shí)間由5秒改成10秒(為了方便觀察,我們?cè)O(shè)置steps第二個(gè)參數(shù)為end,放棄第一幀畫面),然后將原先的動(dòng)畫末態(tài)改到50%,并在動(dòng)畫100%時(shí)增加邊框。·
animation: ani 10s 2s steps(5,end) infinite backwards;
@keyframes ani{
50%{
background-position:0px -750px;
}
100%{
border: 100px solid red;
}
結(jié)果如下圖:
觀察后發(fā)現(xiàn),在10秒的完整動(dòng)畫期間:background-position的變化過程是圖像顯示由1到5,再由5到1,共變化了 【10】 次,而我設(shè)置的steps的number參數(shù)是 【5】,這就打破了上面我說的以整個(gè)動(dòng)畫過程切割成number段的假說。
同時(shí)可以觀察到,border的變化過程共進(jìn)行了5次,因?yàn)槲覀冎辉?00%的時(shí)候設(shè)置了border。
得出結(jié)論: steps的number參數(shù)并不是將整個(gè)動(dòng)畫過程切割成number段,而是對(duì)于某個(gè)css樣式來說,每一段關(guān)鍵幀的變化切割成number段。
假想:上面我們只在動(dòng)畫100%的時(shí)候設(shè)置了100px的boder,如果我們?cè)?0%的時(shí)候也設(shè)置border,并且狀態(tài)恰好是100%的一半,這樣對(duì)于動(dòng)畫0%到100%是一個(gè)流暢的線性變化。請(qǐng)問這時(shí)候動(dòng)畫還會(huì)被切成5段嗎?
觀察發(fā)現(xiàn),動(dòng)畫被切成了10段。
得出結(jié)論: 即使將幾個(gè)關(guān)鍵幀的css變化設(shè)置的具有規(guī)律性,但是steps仍然會(huì)將每段關(guān)鍵幀的變化切割成number段,即只要在這個(gè)關(guān)鍵幀里設(shè)置了某個(gè)css,那么對(duì)于這個(gè)css來說,這個(gè)關(guān)鍵幀就會(huì)被視為steps動(dòng)畫的端點(diǎn)。
那既然每段關(guān)鍵幀都會(huì)被steps切割成number段,那每段的steps動(dòng)畫執(zhí)行的時(shí)間怎么劃分呢?其實(shí)想想就能想到,應(yīng)該是按照關(guān)鍵幀占整個(gè)動(dòng)畫過程的比例分割整個(gè)動(dòng)畫時(shí)間。
如下圖設(shè)置boder:【0%-50%】寬度由0到100,【50%-75%】寬度由100到0,【75%-100%】寬度由0到100
很明顯可以觀察到,border寬度變化的時(shí)間為 2:1:1,即驗(yàn)證了我上面的推論。
下面我舉幾個(gè)steps() 動(dòng)畫的使用場景。
用一張人物動(dòng)作關(guān)鍵幀的長圖,和上面的案例一樣,通過修改背景圖片位置,實(shí)現(xiàn)動(dòng)物或人物的動(dòng)作變化。作為一名蒸愛粉,我給哥哥做了一個(gè)跳舞的動(dòng)畫:
打字機(jī)的原理是用一個(gè)和文字總寬度一樣的div覆蓋文字,并用這個(gè)div的邊框設(shè)置steps()動(dòng)畫實(shí)現(xiàn)光標(biāo)效果,然后減小div寬度(每一幀減小一個(gè)文字的寬度),讓下面文字漏出來就好了~\
點(diǎn)擊運(yùn)行查看效果~
我這里提供了兩種實(shí)現(xiàn)方案,準(zhǔn)確來說是三種:
方案1: var() css變量 + counter-reset計(jì)數(shù)器 + @property規(guī)則 + steps()逐幀動(dòng)畫
使用css變量和counter-reset計(jì)數(shù)器來實(shí)現(xiàn)倒計(jì)時(shí)的數(shù)字,只要設(shè)置動(dòng)畫,在5秒內(nèi)將變量由5變?yōu)?即可實(shí)現(xiàn)倒計(jì)時(shí),但是變量的變化是不會(huì)被瀏覽器添加補(bǔ)間動(dòng)畫的,即只會(huì)在5秒后直接變成0,而不會(huì)有中間,5-4-3-2-1-0的過程,這時(shí)我們?cè)倮聾property關(guān)鍵字為這個(gè)變量配置規(guī)則,實(shí)現(xiàn)數(shù)字變化的動(dòng)態(tài)過程!
而最后出現(xiàn)的 "Go" 可以利用step-end逐幀動(dòng)畫,在5秒后將文字修改成 "Go",或者利用@counter-style關(guān)鍵字自定義計(jì)數(shù)器規(guī)則,在變量變化到0的時(shí)候,定義一個(gè)symbols符號(hào)。
如果你不了解counter-reset、@property和@counter-style,可以查看以下兩篇文章:
CSS counter-reset 屬性
mdn 關(guān)于@property API 說明 mdn 關(guān)于@counter-style 說明
點(diǎn)擊運(yùn)行查看效果~
方案2: 只用steps()逐幀動(dòng)畫
其實(shí)這個(gè)就很簡單了,所有的數(shù)字和最后的 "GO" 都在html里寫死并設(shè)置等高,然后就可以向上面移動(dòng)圖片位置一樣移動(dòng)這些數(shù)字進(jìn)行顯示了。
點(diǎn)擊運(yùn)行查看效果~
平常工作中可以用到steps()逐幀動(dòng)畫的場景也有很多:
原文鏈接:https://juejin.cn/post/7242145254056214583
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。