【效果高能】你不知道的 Animation 動畫技巧

2021-02-18 圖雀社區
引言—

在 web 應用中,前端同學在實現動畫效果時往往常用的幾種方案:

css3 transition / animation - 實現過渡動畫setInterval / setTimeout - 通過設置一個間隔時間來不斷的改變圖像的位置requestAnimationFrame - 通過一個回調函數來改變圖像位置,由系統來決定這個回調函數的執行時機,比定時修改的性能更好,不存在失幀現象

在大多數需求中,css3 的 transition / animation 都能滿足我們的需求,並且相對於 js 實現,可以大大提升我們的開發效率,降低開發成本。

本篇文章將著重對 animation 的使用做個總結,如果你的工作中動畫需求較多,相信本篇文章能夠讓你有所收穫:

Animation 與 Svg 又會擦出怎樣的火花呢?🔥Animation 常用動畫屬性—

介紹完 animation 常用屬性,為了將這些屬性更好地理解與運用,下面將手把手實現一些 DEMO 具體講述

Animation 實現不間斷播報—

實現不間斷播報 DEMO [1]

通過修改內容在父元素中的 y 軸的位置來實現廣播效果

@keyframes scroll {
0%{
transform: translate(0, 0);
}
100%{
transform: translate(0, -$height);
}
}

.ul {
animation-name: scroll;
animation-duration: 5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
/* animation: scroll 5s linear infinite; 動畫屬性簡寫 */
}

此處為了保存廣播滾動效果的連貫性,防止滾動到最後一幀時沒有內容,需要多添加一條重複數據進行填充

<div class="ul">
<div class="li">小劉同學加入了凹凸實驗室</div>
<div class="li">小鄧同學加入了凹凸實驗室</div>
<div class="li">小李同學加入了凹凸實驗室</div>
<div class="li">小王同學加入了凹凸實驗室</div>
<!-- 插入用於填充的數據數據 -->
<div class="li">小劉同學加入了凹凸實驗室</div>
</div>

Animation 實現回彈效果—

通過將過渡動畫拆分為多個階段,每個階段的 top 屬性停留在不同的位置來實現

實現回彈效果 DEMO[2]

/* 規定動畫,改變top,opacity */
@keyframes animate {
0% {
top: -100%;
opacity: 0;
}
25% {
top: 60;
opacity: 1;
}
50% {
top: 48%;
opacity: 1;
}
75% {
top: 52%;
opacity: 1;
}
100%{
top: 50%;
opacity: 1;
}
}

為了讓過渡效果更自然,這裡通過 cubic-bezier() 函數定義一個貝塞爾曲線來控制動畫播放速度

過渡動畫執行完後,為了將讓元素應用動畫最後一幀的屬性值,我們需要使用 animation-fill-mode: forwards

.popup {
animation-name: animate;
animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
animation-iteration-count: 1;
animation-fill-mode: forwards;
/* animation: animate 0.5s cubic-bezier(0.21, 0.85, 1, 1) 1 forwards; 動畫屬性簡寫 */
}

Animation 實現點讚效果—

實現點讚效果 DEMO [3]

相信大多數同學都知道點讚效果,本文章會實現一個簡易版的點讚效果,主要講述一下實現思路:

為了讓氣泡可以向上偏移,我們需要先實現一個 y 軸方向上移動的 @keyframes 動畫
/* 規定動畫,改變y軸偏移距離*/
@keyframes animation-y {
0%{
transform: translate(-50%, 100px) scale(0);
}
50%{
transform: translate(-50%, -100px) scale(1.5);
}
100%{
transform: translate(-50%, -300px) scale(1.5);
}
}

為了讓氣泡向上偏移時顯得不太單調,我們可以再實現一個 x 軸方向上移動的 @keyframes 動畫
/* 規定動畫,改變x軸偏移距離 */
@keyframes animation-x {
0%{
margin-left: 0px;
}
25%{
margin-left: 25px;
}
75%{
margin-left: -25px;
}
100%{
margin-left: 0px;
}
}

這裡我理解:

雖然是修改 margin 來改變 x 軸偏移距離,但實際上與修改 transform沒有太大的性能差異因為通過 @keyframes animation-y 中的 transform 已經新建了一個渲染層 ( PaintLayers )animation 屬性 可以讓該渲染層提升至 合成層(Compositing Layers) 擁有單獨的圖形層 ( GraphicsLayer ),即開啟了硬體加速 ,不會影響其他渲染層的 paint、layout對於合成層(Compositing Layers)相關知識不是很了解的同學,可以閱讀一下凹凸實驗室(http://aotu.io)的文章《從瀏覽器渲染層面解析 css3 動效優化原理》

如筆者這裡理解有誤,還請讀者大佬指出,感激不盡~

給氣泡應用上我們所實現的兩個 @keyframes 動畫
.bubble {
animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
/* 給 bubble 開啟了硬體加速 */
}

在點讚事件中,通過 js 操作動態添加/移除氣泡元素
function like() {
const likeDom = document.createElement('div');
likeDom.className = 'bubble'; // 添加樣式
document.body.appendChild(likeDom); // 添加元素
setTimeout( () => {
document.body.removeChild(likeDom); // 移除元素
}, 4000)
}

Animation 與 Svg 繪製 loading/進度條 組件 🔥—

Animation 與 Svg 繪製 loading/進度條 組件 🔥 DEMO [4]

首先,我們使用 svg 繪製一個圓周長為2 * 25 * PI = 157 的圓
<svg with='200' height='200' viewBox="0 0 100 100"  >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke="#0079f5" ></circie>
</svg>

將實線圓繪製成虛線圓,這裡需要用 stoke-dasharray:50, 50 (可簡寫為50) 屬性來繪製虛線, stoke-dasharray 參考資料[5]它的值是一個數列,數與數之間用逗號或者空白隔開,指定短劃線(50px)和缺口(50px)的長度。由於50(短劃線) + 50(缺口) + 50(段劃線) = 150, 150 < 157,無法繪製出完整的圓,所以會導致右邊存在缺口(7px)
<svg with='200' height='200' viewBox="0 0 100 100"  >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" ></circie>
</svg>

stroke-dashoffset 屬性可以使圓的短劃線和缺口產生偏移,添加 @keyframes 動畫後能夠實現從無到有的效果,stoke-dashoffset 參考資料[6]設置 stroke-dasharray="157 157",指定 短劃線(157px) 和 缺口(157px) 的長度。添加 @keyframes 動畫 修改stroke-dashoffset值, 值為正數時逆時針偏移🔄,, 值為負數時,順時針偏移🔃
@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -157; /* 線條順時針偏移 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}

為了讓 loading 組件線條可見,我們需要一個50px的短劃線,設置 stroke-dasharray="50"為了讓短劃線發生偏移後可以完全消失,缺口需要大於或等於圓周長157,設置 stroke-dasharray="50 157"添加 @keyframes 動畫,為了讓動畫結束時仍處理動畫開始位置,需要修改 stroke-dashoffset:-207(短劃線+缺口長度)進度條也是類似原理,幫助理解 stroke-dashoffset 屬性,具體實現請查看示例[7]
@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -207; /* 保證動畫結束時仍處理動畫開始位置 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}

Animation steps()運用—

steps() 是 animation-timing-function 的屬性值

animation-timing-function : steps(number[, end | start])

steps 函數指定了一個階躍函數,它接受兩個參數第一個參數接受一個整數值,表示兩個關鍵幀之間分幾步完成第二個參數有兩個值 start or end。默認值為 endstep-start 等同於 step(1, start)。step-end 等同於 step(1, end)

steps 適用於關鍵幀動畫,第一個參數將兩個關鍵幀細分為N幀,第二個參數決定從一幀到另一幀的中間間隔是用開始幀還是結束幀來進行填充。

看下圖可以發現:

steps(N, start)將動畫分為N段,動畫在每一段的起點發生階躍(即圖中的空心圓 → 實心圓),動畫結束時停留在了第 N 幀steps(N, end)將動畫分為N段,動畫在每一段的終點發生階躍(即圖中的空心圓 → 實心圓),動畫結束時第 N 幀已經被跳過(即圖中的空心圓 → 實心圓),停留在了 N+1 幀。實踐出真知!—Animation 實現打字效果

Animation 實現打字效果 DEMO[8]

此處用英文字母(I'm an O2man.)舉例,一共有13個字符。[經測試,多數中文字體每個字符寬高都相等]steps(13)可以將 @keyframes 動畫分為13階段運行,且每一階段運行距離相等。

效果如下:

/* 改變容器寬度 */
@keyframes animate-x {
0%{
width: 0;
}
}

p {
width: 125px;
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards;
}

可以發現僅僅這樣還不夠,動畫運行過程中出現了字符被截斷的情況,為了保證每個階段運行後能準確無誤地顯示當前所處階段的字符,我們還需要保證每個字符的width與動畫每一階段運行的距離相等設置Monaco字體屬性,用以保證每個字符的 width 相同,具體像素受fontSize屬性影響,示例中的字體寬度約為 9.6px,9.6px * 13(段數) = 124.8px (125px),所以當我們設置容器寬度為 125px,即可的達成目的:每個字符的 width 與動畫每一階段運行的距離相等(約為 9.6px )。
p {
/* 設置 Monaco 字體屬性,字體大小為16px,用以保證每個字符的 width 相同,width 約為9.6p */
font-family: Monaco;
/* 9.6px * 13 = 124.8px (125px) */
width: 125px ;
font-size: 16px;
overflow: hidden;
border-right: 1px solid transparent;
/* 同時應用動畫 animate-x、cursor-x */
animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
}

Animation 實現幀動畫 ⏰

Animation 實現幀動畫 ⏰ DEMO [9]

這裡我們拿到了一張47幀的雪碧圖(css spirit)[10],設置背景圖
.main {
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
}

添加 @keyframes 修改 background-position,讓背景圖移動
@keyframes animate {
0% {
background-position: 0 0;
}

100% {
background-position: 0 100%;
}
}
.main{
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
animation: animate 2s 1s steps(47) infinite alternate;
}

同時, css 還提供了animation-play-state用於控制動畫是否暫停
input:checked+.main{
animation-play-state: paused;
}

文章篇幅較長,感謝大家的閱讀,希望各位看客能夠有所收穫~ ~ ~

相關參考資料

《Animation 常用動畫屬性》[11]

《CSS 參考手冊》[12]

《steps 參考資料》[13]

《SVG 學習之 stroke-dasharray 和 stroke-dashoffset 詳解》[14]

《理解 CSS3 Animation 中的 steps》[15]

《【譯】css 動畫裡的 steps 用法詳解》[16]

《CSS Will Change》[17]

參考資料[1]

實現不間斷播報 DEMO : https://codepen.io/awesomedevin/pen/wvMGEaY

[2]

實現回彈效果 DEMO: https://codepen.io/awesomedevin/pen/wvMGEaY

[3]

實現點讚效果 DEMO : https://codepen.io/awesomedevin/pen/dyGXEar

[4]

Animation 與 Svg 繪製 loading/進度條 組件 🔥 DEMO : https://codepen.io/awesomedevin/pen/zYromBB

[5]

stoke-dasharray 參考資料: https://www.cnblogs.com/daisygogogo/p/11044353.html

[6]

stoke-dashoffset 參考資料: https://www.cnblogs.com/daisygogogo/p/11044353.html

[7]

示例: https://codepen.io/awesomedevin/pen/zYromBB

[8]

Animation 實現打字效果 DEMO: https://codepen.io/awesomedevin/pen/xxZEjjO

[9]

Animation 實現幀動畫 ⏰ DEMO : https://codepen.io/awesomedevin/pen/JjGRMgN

[10]

雪碧圖(css spirit): https://img11.360buyimg.com/ling/jfs/t1/142743/11/2314/166268/5f046114Efb97efac/b327092864ed1f04.png

[11]

Animation 常用動畫屬性: https://www.w3school.com.cn/cssref/index.asp

[12]

CSS 參考手冊: https://www.w3school.com.cn/cssref/index.asp

[13]

steps 參考資料: https://segmentfault.com/a/1190000007042048

[14]

SVG 學習之 stroke-dasharray 和 stroke-dashoffset 詳解: https://www.cnblogs.com/daisygogogo/p/11044353.html

[15]

理解 CSS3 Animation 中的 steps: https://laixiazheteng.com/article/page/id/0gU2Wefas7hn

[16]

【譯】css 動畫裡的 steps 用法詳解: https://segmentfault.com/a/1190000007042048

[17]

CSS Will Change: https://developer.mozilla.org/zh-CN/docs/Web/CSS/will-change

相關焦點

  • 你可能不知道的 CSS 動畫技巧與細節
    怕標題起的有點大,下述技巧如果你已經掌握了看看就好,歡迎斧正,本文希望通過介紹一些 CSS 不太常用的技巧,輔以一些實踐,讓讀者可以更加深入的理解掌握 CSS 動畫。廢話少說,直接進入正題,本文提到的動畫不加特殊說明,皆指 CSS 動畫。
  • 深入理解CSS3 Animation 幀動畫
    我們知道CSS3的Animation有八個屬性animation-nameanimation-durationanimation-delayanimation-iteration-countanimation-directionanimation-play-stateanimation-fill-mode
  • Web Animation 製作指南
    CSS Animation製作Web動畫分為三部分:聲明動畫:通過定製關鍵幀(@keyframes)來聲明一個動畫,這個關鍵相當於Flash動畫、GIF動畫圖中的幀,主要用於控制CSS Animation效果調用動畫:在CSS中對應的元素上通過animation屬性調用聲明好的對應動畫,並且指定動畫播放的一些特性
  • 如何在鴻蒙中實現一個animation動畫?
    要實現一個 animation 動畫,需要使用兩個屬性 keyframes 和 animation。定義動畫在不同階段的狀態.所製作的動畫就根據 keyframes 中定義的規則運動。它的語法結構如下兩種:如下圖:
  • PPT動畫效果製作技巧,你掌握了嗎?
    我們經常會看到一些「PPT大神」製作的PPT,他們的動畫總是能夠第一眼就吸引了我們,整個PPT的製作看上去酷炫又富有創意,能達到這種製作水平想必背後下了不少功夫,少不了長時間去積累掌握各種技巧與學習,那麼我們也能不能達到這種程度呢,首先我們要知道並去掌握PPT的動畫效果製作技巧。
  • Creating Audio Awesomeness For Animation | 為動畫賦予音頻魅力
    無論設計多美,動態多麼流暢,動畫的成功都取決於聲音。雖然我們可以在沒有聲音的情況下與真實的動作聯繫起來,但是無聲的動畫很容易變成形狀、顏色和不清晰場景組合的抽象序列而已。我們需要音樂或音效來牽繞、吸引我們,來引導我們貫穿故事。
  • 「Best Animation KISS! 」葡萄牙動畫人Abi Feijó講座實錄
    很長一段時間裡我都會在尋找可以創作的有趣的點子,我知道了自己想要的是什麼,也知道我喜歡的是什麼,直到遇到這個故事。這就是我想要做的項目,因為我在看到這個故事之前我並不知道這個事件背後的事情,我想如果我不知道的話那更多的人也不知道。所以我覺得我有職責把它做成一部動畫電影然後將它展示給更多的人。
  • 來自她們——中國藝術動畫 From Hers | Chinese Art Animation
    爸爸總對囡囡撒各種謊,這讓囡囡漸漸開始不相信她的爸爸了。Brief DescriptionNunu's single-parent father tells his 4-year-old daughter that there is a cow at the bottom of her milk cup.
  • 使用CSS技術實現Netflix Logo動畫效果
    第一個概念因為我想要嘗試某些技術方案導致我的第一種實現方式有些累贅。例如:我想使用純 CSS 技術來實現它,並且我也想當我點擊按鈕的時候,這個動畫再執行一次,所以我要使用一些不可思議技巧。幸運的是當我寫 CSS 代碼的時候,總會有一些小技巧會在我的腦海裡湧現。我們來談論一下實際的動畫。
  • Android幀動畫和補間動畫看這篇足夠了
    所以本文要有更多思考分析之外,也會教大家一些關於動畫的小技巧和可能踩到的坑。本文我們就先來研究幀動畫和補間動畫,話不多說,現在開始我們的內容吧。幀動畫我們由簡到難,先來講講幀動畫。設備的開機動畫及其「複雜」的效果,看似不可能完成的動畫設備的開機動畫界面這個沒什麼好解釋的,據我所知市面上99%的機器都是這麼做的,因為這個時候系統或資源還沒準備完全,所以就肯定會選擇幀動畫。
  • CSS3動畫,為你帶來極致的視覺體驗!
    所以在當前,大量的動畫效果由原來的JavaScript製作正慢慢的被CSS3所替代,究其原因在於CSS3的性能會比JS的性能來的好,並且CSS3動畫為用戶帶來了強大而又震撼的效果,為開發者帶來了簡單的書寫方式。
  • PPT幻燈片設計動畫效果的五大技巧
    不過用PPT做些不可思議的動畫還是可以的,做些炫的效果也是很能唬人的。1、「動畫」欄這裡可以快速添加進入、強調、退出、路徑動畫。有下拉菜單,圖略。2、效果選項欄這裡可以進一步設置動畫方式。比如給給一對象添加「飛入」進入動畫,可以有8個方位的選擇。
  • 【English Corner | Movies, Animation and Anime】
    Movies, animation and anime have developed into mature industries in modern days. 電影、動漫和動畫在現代已經發展成為成熟的產業。它們通常表現為動漫、漫畫、雜誌、展映影片、電視節目、音像製品、舞臺劇,以及基於現代信息通信技術的動漫直銷產品的開發、製作、出版、播出、演出、銷售等。
  • 好看的皮囊千篇一律,有趣的動畫讓人放不下手機
    正文初話動畫動畫,一直是前端程序設計中無法避免的一環。它不像基礎組件和網絡請求組件等那樣必不可少,但是開發當中如果沒有動畫,那麼我們的程序可能無法成為一款優秀的作品。沒錯,動畫是讓你的程序能被稱為優秀的其中不可或缺的一步。一般的動畫分為幾種——逐幀動畫、補間動畫、基於物理的動畫等。
  • SVG動畫、CSS3動畫常用知識點全解析
    3.animateMotion之前所有動畫功能在css裡都可以用animation實現,但<animateMotion>可以讓父元素沿著指定的路徑運動。也可以使用path指定複雜的路徑,或者可以指定<mpath>元素作為自己的路徑。效果如下:
  • Android動畫:這些補間動畫的使用你必須要了解!
    今天,我將介紹Android補間動畫的基礎使用,包括平移、旋轉、透明度等,希望你們會喜歡。閱讀本文前,請先閱讀文章:Android動畫:手把手帶你學習補間動畫    註:最近公眾號推送的專題是Android動畫,感興趣的讀者可以及時關注。
  • 【攝影技巧】抱歉,這麼棒的動圖製作方法現在才跟你們說
    會動的照片這種創意攝影的技法,說簡單不簡單,說難也不是很難,但還是要具備基礎的攝影觀念以及後製技巧。技法是其次,重要的是有沒有辦法找到有趣的點切入。如果覺得後製軟體對你來說太困難的話,現在也利用手機APP,也可以製作會動的照片哦!有了想法,技法是很好克服的,有興趣的朋友可以自己試著做做看吧!動圖
  • @所有動畫人,這些好用的APP你不能不知道
    雖然你也可以在有限的選擇中玩出無窮的花樣。如果你不滿足於Folioscope的簡潔,那麼接下來這款app應該可以滿足你的需要。Animator是我最常用的軟體。安卓和蘋果iOS應該都有的。這個app有兩個版本,藍色的是最新版,而舊的橙色的版本除了顏料桶沒有也沒什麼不同。但是有一個新版沒有的好處,那就是橫屏。
  • 使用 SVG 製作加載動畫
    但是要麼效果好的導出的 GIF 體積特別大,看了下有 8M 多了,要麼體積小的 GIF 效果又特別不清楚。然後我看了下效果,發現其實用 SVG 動畫來實現應該比較簡單,於是就和設計師要了一下原始的稿子導出成 SVG 後處理了下。將 AE 動效稿子轉成 SVG 動畫的話 Airbnb 有出過一款 Lottie 的工具。
  • AE角色動畫技巧——Pose to Pose【從姿態到姿態】
    角色動畫很困難。更糟糕的是,大多數AE動畫師利用移動LOGO和文字的方式去移動角色:直接向前移動。掌握角色動畫的訣竅其實是使用迪士尼動畫師在cel動畫鼎盛時期使用的方法:從一種姿勢到另一種姿勢(Pose-to-Pose)。在本教程中,角色動畫百科全書摩根威廉士將教你神奇的從姿勢到姿勢的方法,以及如何在AE中使用它。