javascript
CSS或JS实现逐帧动画方案
什么是逐幀動(dòng)畫
????????逐幀動(dòng)畫是一種在連續(xù)的關(guān)鍵幀中分解動(dòng)畫動(dòng)作,即在時(shí)間軸的每一幀上繪制不同內(nèi)容并使之連續(xù)播放成動(dòng)畫的一種常見的動(dòng)畫形式。與CSS關(guān)鍵幀動(dòng)畫不同的是,逐幀動(dòng)畫每一幀需要自行定義;關(guān)鍵幀動(dòng)畫只需定義部分關(guān)鍵幀,由計(jì)算機(jī)插值計(jì)算出這些關(guān)鍵幀之間的中間幀。
? ? ? ? 逐幀動(dòng)畫的源文件要求:每一幀畫面的寬高最好相等,使用精靈圖時(shí),盡量做到每一幀畫面中間無空隙,否則難以定義動(dòng)畫繪制方式。
逐幀動(dòng)畫的源文件如下:
單行逐幀動(dòng)畫 多行逐幀動(dòng)畫使用CSS繪制逐幀動(dòng)畫
?????????CSS timing-function的steps函數(shù)會(huì)在關(guān)鍵幀中等分插入指定數(shù)目的離散的中間幀,使動(dòng)畫跳躍式播放。當(dāng)存在多個(gè)關(guān)鍵幀時(shí),如steps(5) 0% 50% 100%,則css會(huì)在每?jī)蓚€(gè)關(guān)鍵幀中間都插入5個(gè)中間幀。
使用方法如下:
.animation-example{background-position: 0 0;animation: stepsAnimation 1s steps(23); } @keyframes stepsAnimation {0% {background-position: 0 0;}100% {background-position: 0 100%;} }.transition-example{background-position: 0 0;transition: background-position 1s steps(23); } .transition-example:hover{background-position: 0 100%; }????????所有可以移動(dòng)圖片的屬性(如:background-position、left、transform)都可以用于繪制幀動(dòng)畫。主要原理是 元素每次將只展示一幀,其余幀被遮擋,通過steps函數(shù)間斷地移動(dòng)圖片,跳躍到剩余的幀。?
單行幀動(dòng)畫繪制方法:
? ? ? ? 以background-position屬性為例,元素寬高定義為一幀畫面的寬高(或等比例伸縮),并定義背景圖片為幀動(dòng)畫圖片,定義background-size將一幀畫面顯示在元素中并隱藏住其余幀。定義動(dòng)畫屬性,steps(幀數(shù) - 1) ——減一是因?yàn)樽詈笠粠?00%已被定義,僅需插入其余幀定義即可。
.animation{width: 103px;height: 103px;background: url("./statics/management-icon.png") no-repeat;background-position: 0 0;background-size: 100%;/** 該幀動(dòng)畫有24幀畫面,在2s內(nèi)播放完成 */animation: stepsAnimation 2s steps(23); } @keyframes stepsAnimation {0% {background-position: 0 0;}100% {background-position: 0 100%;} }多行逐幀動(dòng)畫繪制方法:
? ? ? ? 僅animaiton的定義與單行的不同:在定義@keyframes時(shí)需要自行定義每一幀的位置、狀態(tài),并且timing-function為steps(1)。
? ? ? ? 建議使用less或scss計(jì)算每一幀的定義。或使用我開發(fā)的一個(gè)工具。
Multiline Keyframes Generator
.unlock{width: 50px;height: 66px;background-repeat: no-repeat;background-image: url(/v/iphone-se/j/images/overview/privacy/privacy_animated__dbfct2heugsy_medium.png);background-size: 450px 264px;background-position: 0px 0px;animation: unlock_animation-medium 3s steps(1); } @keyframes unlock_animation-large {0% {background-position: 0px 0px}2.7777777778% {background-position: -66px 0px}5.5555555556% {background-position: -132px 0px}8.3333333333% {background-position: -198px 0px}11.1111111111% {background-position: -264px 0px}13.8888888889% {background-position: -330px 0px}16.6666666667% {background-position: 0px -88px}19.4444444444% {background-position: -66px -88px}22.2222222222% {background-position: -132px -88px}25% {background-position: -198px -88px}27.7777777778% {background-position: -264px -88px}30.5555555556% {background-position: -330px -88px}33.3333333333% {background-position: 0px -176px}36.1111111111% {background-position: -66px -176px}38.8888888889% {background-position: -132px -176px}41.6666666667% {background-position: -198px -176px}44.4444444444% {background-position: -264px -176px}47.2222222222% {background-position: -330px -176px}50% {background-position: 0px -264px}52.7777777778% {background-position: -66px -264px}55.5555555556% {background-position: -132px -264px}58.3333333333% {background-position: -198px -264px}61.1111111111% {background-position: -264px -264px}63.8888888889% {background-position: -330px -264px}66.6666666667% {background-position: 0px -352px}69.4444444444% {background-position: -66px -352px}72.2222222222% {background-position: -132px -352px}75% {background-position: -198px -352px}77.7777777778% {background-position: -264px -352px}80.5555555556% {background-position: -330px -352px}83.3333333333% {background-position: 0px -440px}86.1111111111% {background-position: -66px -440px}88.8888888889% {background-position: -132px -440px}91.6666666667% {background-position: -198px -440px}94.4444444444% {background-position: -264px -440px}97.2222222222% {background-position: -330px -440px}to {background-position: -330px -440px} }缺點(diǎn)(已解決)?
? ? ? ? 使用CSS繪制逐幀動(dòng)畫的自定義能力不高,比較適合動(dòng)畫連續(xù)播放;transition與animation難以做到中斷并回退,不適用于有每一幀由自己控制播放、中斷、回退、跳幀這一類需求的效果。
缺點(diǎn)解決方案,如何控制每一幀的播放
? ? ? ? 參考Apple官網(wǎng) iPhone SE產(chǎn)品界面介紹的動(dòng)畫。
? ? ? ? 將動(dòng)畫直接暫停,并將播放時(shí)長(zhǎng)與幀數(shù)等長(zhǎng),使用js更改animation-delay控制每一幀的播放。animation-delay定義一個(gè)負(fù)值會(huì)讓動(dòng)畫立即開始。但是動(dòng)畫會(huì)從它的動(dòng)畫序列中某位置開始。例如,如果設(shè)定值為 -1s,動(dòng)畫會(huì)從它的動(dòng)畫序列的第 1 秒位置處立即開始。
.animation{background-repeat: no-repeat;background-image: url(/v/iphone-se/j/images/overview/privacy/privacy_animated__dbfct2heugsy_medium.png);background-size: 450px 264px;width: 50px;height: 66px;animation: unlock_animation-medium 36s steps(1) forwards;/** 暫停動(dòng)畫,由自己控制動(dòng)畫播放 */animation-play-state: paused;animation-iteration-count: 1;/** 動(dòng)畫總共36幀,則duration為36s */animation-duration: 36s;background-position: 0px 0px; }/** 使用js更改animation-delay,控制動(dòng)畫播放 */ <div class='animation' style='animation-delay: -6s;'></div>? ? ? ? 此時(shí)CSS便僅用于動(dòng)畫幀的定義,動(dòng)畫幀的播放則通過js自定義。
使用js繪制逐幀動(dòng)畫?(不推薦)
????????在使用CSS繪制逐幀動(dòng)畫前我遇到一個(gè)困難,CSS逐幀動(dòng)畫完全自動(dòng)播放,難以控制中斷或中斷后回退等功能(已解決),所以我封裝了一個(gè)js庫用于繪制逐幀動(dòng)畫。
https://github.com/YThinker/frame-animationhttps://github.com/YThinker/frame-animation/tree/master? ? ? ? 包含:SinglelineFrameAnimation 用于繪制單行逐幀動(dòng)畫;MultilineFrameAnimation 多行逐幀動(dòng)畫繪制。可選擇使用transform,background,image src等屬性繪制,包括了無限循環(huán)、往復(fù)播放、延遲播放等功能。
example頁面
FrameByFrame Animation Example
使用img src配合js繪制逐幀動(dòng)畫(不推薦)
? ? ? ? 原理非常簡(jiǎn)單,將每一幀圖片導(dǎo)出為單獨(dú)的圖片,通過替換img src的方式播放每一幀畫面,該方法非常簡(jiǎn)單,但是用戶體驗(yàn)差,會(huì)導(dǎo)致請(qǐng)求次數(shù)過多,可以通過預(yù)加載的方式優(yōu)化。
總結(jié)
以上是生活随笔為你收集整理的CSS或JS实现逐帧动画方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 逐帧动画(Frame Animation
- 下一篇: JS实现浏览器打印Word