這篇文章帶給大家的內容是關於如何使用CSS和GSAP實現有多個關鍵幀的連續動畫(附源碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
https://github.com/comehope/front- end-daily-challenges
定義dom,容器中包含10 個p
子元素,每個p
中包含1 個span
元素:
<figure class="container"> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> </figure>
居中顯示:
body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: lightyellow; }
定義容器的尺寸和樣式:
.container { width: 400px; height: 400px; background: linear-gradient(45deg, tomato, gold); border-radius: 3%; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); }
畫出容器裡的1 個元素,它有一個外殼p
,裡面是一個白色的小方塊span
:
.container { position: relative; } .container p { position: absolute; width: inherit; height: inherit; display: flex; align-items: center; justify-content: center; } .container p span { position: absolute; width: 40px; height: 40px; background-color: white; }
為容器中的元素定義下標變量,並讓元素的外殼依次旋轉,圍合成一個圓形,其中outline
是輔助線:
.container p { outline: 1px dashed black; transform: rotate(calc((var(--n) - 1) * 36deg)); } .container p:nth-child(1) { --n: 1; } .container p:nth-child(2) { --n: 2; } .container p:nth-child(3) { --n: 3; } .container p:nth-child(4) { --n: 4; } .container p:nth-child(5) { --n: 5; } .container p:nth-child(6) { --n: 6; } .container p:nth-child(7) { --n: 7; } .container p:nth-child(8) { --n: 8; } .container p:nth-child(9) { --n: 9; } .container p:nth-child(10) { --n: 10; }
至此,子元素繪製完成,接下來開始寫動畫腳本。
引入GSAP 庫:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
定義一個變量,代表子元素選擇器:
let elements = '.container p span';
宣告一個時間軸物件:
let animation = new TimelineMax();
先設定入場方式為由小(第1幀)變大(第2幀),其中並沒有第2 幀的代碼,它是隱含在語義中的:
animation.from(elements, 1, {scale: 0});
讓子元素變成豎長條,向四周散開(第3格):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25});
讓豎長條旋轉著變成小方塊(第4幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180});
讓小方塊變成橫長條,圍成一個圓形(第5幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1});
注意,因scrimba 在錄製過多幀時會崩潰,所以第6 幀至第11 幀沒有在影片中體現。
讓圓形向內收斂,同時線條變細(第6幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1});
讓線條向左擺動(第7幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'});
再讓線條向右擺動(第8格):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'});
再把橫線變成垂直線,造型與第3 格相似,只是線更細,更向內收斂(第9格):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1});
再把垂直線變成橫線,造型與第5 格相似,但線短一些(第10格):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1}) .to(elements, 1, {scaleX: 0.5, scaleY: 0.1})
橫線稍向外擴散,變成圓點(第11幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1}) .to(elements, 1, {scaleX: 0.5, scaleY: 0.1}) .to(elements, 1, {y: '-80px', scaleY: 0.5, borderRadius: '50%'});
讓圓點變形為垂直線,並向內收縮,這個變化的距離長,所以動畫時間也要長一些(第12格):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1}) .to(elements, 1, {scaleX: 0.5, scaleY: 0.1}) .to(elements, 1, {y: '-80px', scaleY: 0.5, borderRadius: '50%'}) .to(elements, 1, {y: '-10px', scaleX: 0.1, scaleY: 0.5, borderRadius: '0%', rotation: 0});
讓豎線從中心向外快速擴散,擴散前稍停片刻,好像線條都被發射出一樣(第13幀):
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1}) .to(elements, 1, {scaleX: 0.5, scaleY: 0.1}) .to(elements, 1, {y: '-80px', scaleY: 0.5, borderRadius: '50%'}) .to(elements, 1, {y: '-10px', scaleX: 0.1, scaleY: 0.5, borderRadius: '0%', rotation: 0}) .to(elements, 1, {y: '-300px', delay: 0.5});
用時間尺度縮放函數讓動畫播放速度加快一倍:
animation.from(elements, 1, {scale: 0}) .to(elements, 1, {y: '-100px', scaleX: 0.25}) .to(elements, 1, {scaleY: 0.25, rotation: 180}) .to(elements, 1, {scaleX: 1}) .to(elements, 1, {y: '-60px', scaleY: 0.1}) .to(elements, 1, {x: '-30px'}) .to(elements, 1, {x: '30px'}) .to(elements, 1, {x: '0', scaleX: 0.1, scaleY: 1}) .to(elements, 1, {scaleX: 0.5, scaleY: 0.1}) .to(elements, 1, {y: '-80px', scaleY: 0.5, borderRadius: '50%'}) .to(elements, 1, {y: '-10px', scaleX: 0.1, scaleY: 0.5, borderRadius: '0%', rotation: 0}) .to(elements, 1, {y: '-300px', delay: 0.5}) .timeScale(2);
修改宣告時間軸的程式碼,使動畫重複播放:
let animation = new TimelineMax({repeat: -1, repeatDelay: 1});
至此,動畫完成。
隱藏容器外的內容,並刪除輔助線;
.container { overflow: hidden; } .container p { /* outline: 1px dashed black; */ }
最後,裝飾一下頁面的角落:
body { overflow: hidden; } body::before, body::after { content: ''; position: absolute; width: 60vmin; height: 60vmin; border-radius: 50%; background: radial-gradient( transparent 25%, gold 25%, gold 50%, tomato 50% ); } body::before { left: -30vmin; bottom: -30vmin; } body::after { right: -30vmin; top: -30vmin; }
大功告成!
相關推薦:
#以上是如何使用CSS和GSAP實現有多個關鍵影格的連續動畫(附源碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!