javascript
CSS或JS实现逐帧动画方案
什么是逐幀動畫
????????逐幀動畫是一種在連續的關鍵幀中分解動畫動作,即在時間軸的每一幀上繪制不同內容并使之連續播放成動畫的一種常見的動畫形式。與CSS關鍵幀動畫不同的是,逐幀動畫每一幀需要自行定義;關鍵幀動畫只需定義部分關鍵幀,由計算機插值計算出這些關鍵幀之間的中間幀。
? ? ? ? 逐幀動畫的源文件要求:每一幀畫面的寬高最好相等,使用精靈圖時,盡量做到每一幀畫面中間無空隙,否則難以定義動畫繪制方式。
逐幀動畫的源文件如下:
單行逐幀動畫 多行逐幀動畫使用CSS繪制逐幀動畫
?????????CSS timing-function的steps函數會在關鍵幀中等分插入指定數目的離散的中間幀,使動畫跳躍式播放。當存在多個關鍵幀時,如steps(5) 0% 50% 100%,則css會在每兩個關鍵幀中間都插入5個中間幀。
使用方法如下:
.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%; }????????所有可以移動圖片的屬性(如:background-position、left、transform)都可以用于繪制幀動畫。主要原理是 元素每次將只展示一幀,其余幀被遮擋,通過steps函數間斷地移動圖片,跳躍到剩余的幀。?
單行幀動畫繪制方法:
? ? ? ? 以background-position屬性為例,元素寬高定義為一幀畫面的寬高(或等比例伸縮),并定義背景圖片為幀動畫圖片,定義background-size將一幀畫面顯示在元素中并隱藏住其余幀。定義動畫屬性,steps(幀數 - 1) ——減一是因為最后一幀100%已被定義,僅需插入其余幀定義即可。
.animation{width: 103px;height: 103px;background: url("./statics/management-icon.png") no-repeat;background-position: 0 0;background-size: 100%;/** 該幀動畫有24幀畫面,在2s內播放完成 */animation: stepsAnimation 2s steps(23); } @keyframes stepsAnimation {0% {background-position: 0 0;}100% {background-position: 0 100%;} }多行逐幀動畫繪制方法:
? ? ? ? 僅animaiton的定義與單行的不同:在定義@keyframes時需要自行定義每一幀的位置、狀態,并且timing-function為steps(1)。
? ? ? ? 建議使用less或scss計算每一幀的定義。或使用我開發的一個工具。
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} }缺點(已解決)?
? ? ? ? 使用CSS繪制逐幀動畫的自定義能力不高,比較適合動畫連續播放;transition與animation難以做到中斷并回退,不適用于有每一幀由自己控制播放、中斷、回退、跳幀這一類需求的效果。
缺點解決方案,如何控制每一幀的播放
? ? ? ? 參考Apple官網 iPhone SE產品界面介紹的動畫。
? ? ? ? 將動畫直接暫停,并將播放時長與幀數等長,使用js更改animation-delay控制每一幀的播放。animation-delay定義一個負值會讓動畫立即開始。但是動畫會從它的動畫序列中某位置開始。例如,如果設定值為 -1s,動畫會從它的動畫序列的第 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;/** 暫停動畫,由自己控制動畫播放 */animation-play-state: paused;animation-iteration-count: 1;/** 動畫總共36幀,則duration為36s */animation-duration: 36s;background-position: 0px 0px; }/** 使用js更改animation-delay,控制動畫播放 */ <div class='animation' style='animation-delay: -6s;'></div>? ? ? ? 此時CSS便僅用于動畫幀的定義,動畫幀的播放則通過js自定義。
使用js繪制逐幀動畫?(不推薦)
????????在使用CSS繪制逐幀動畫前我遇到一個困難,CSS逐幀動畫完全自動播放,難以控制中斷或中斷后回退等功能(已解決),所以我封裝了一個js庫用于繪制逐幀動畫。
https://github.com/YThinker/frame-animationhttps://github.com/YThinker/frame-animation/tree/master? ? ? ? 包含:SinglelineFrameAnimation 用于繪制單行逐幀動畫;MultilineFrameAnimation 多行逐幀動畫繪制。可選擇使用transform,background,image src等屬性繪制,包括了無限循環、往復播放、延遲播放等功能。
example頁面
FrameByFrame Animation Example
使用img src配合js繪制逐幀動畫(不推薦)
? ? ? ? 原理非常簡單,將每一幀圖片導出為單獨的圖片,通過替換img src的方式播放每一幀畫面,該方法非常簡單,但是用戶體驗差,會導致請求次數過多,可以通過預加載的方式優化。
總結
以上是生活随笔為你收集整理的CSS或JS实现逐帧动画方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 逐帧动画(Frame Animation
- 下一篇: 2023 新年倒计时HTML源码