# JS動畫製作 JS的第一個應用,就先從動畫開始好了 ## GSAP動畫 目標是做出能讓網頁元素隨著向下滑動淡入,且不同元素有不同的進場方向的動畫,而在眾多的libraries中我選擇用GSAP,沒為什麼,只是找到的資源比較多XD ### GSAP起手式 要先從HTML引入library,一個是主library,一個是額外的ScrollTrigger ```htmlembedded= <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/ScrollTrigger.min.js"></script> ``` 而JS裡面要有ScrollTrigger的Plugin ```javascript= gsap.registerPlugin(ScrollTrigger); ``` 這樣環境就架設好了,開始打酷酷的動畫吧~ ### 主動畫製作 講講GSAP 3的基礎語法 ```javascript= gsap.from(".keyboard", { //選取物件 scrollTrigger: { trigger: ".keyboard", start: "top 30%", //當物件抵達視窗30%高度時開始 end: "bottom 100%", //當物件抵達視窗底部時結束 scrub: true, //動畫隨著捲動推移 toggleActions: "restart pause reverse pause" //在視窗外不移動,往上捲時動畫倒轉 }, //scrollTrigger特效 opacity: 0, //從透明淡入 duration: 1.5, //維持1.5s x: 25*1.73, //x方向位移 y: 25 //y方向位移 }); ``` 如此一來鍵盤就有了進場動畫 ![](https://i.imgur.com/kuNjQxC.gif) 但因為再幫螢幕、視窗一、視窗二等其他三個元素寫三次相似的code有點不美觀,所以我把他們統整到陣列跟object裡,用字串格式化美化 ```javascript= const hobbyElements = [ {name: "keyboard", x: 25*1.73, y: 25}, {name: "window1", x: -25*1.73, y: 25}, {name: "window2", x: 25*1.73, y: -25}, {name: "screen", x: -25*1.73, y: -25} ]; for(hobbyElement of hobbyElements) { gsap.from(`.${hobbyElement.name}`, { scrollTrigger: { trigger: `.${hobbyElement.name}`, start: "top 30%", end: "bottom 100%", scrub: true, toggleActions: "restart pause reverse pause" }, opacity: 0, duration: 1.5, x: hobbyElement.x, y: hobbyElement.y }); } ``` 然後就能得到更酷的動畫 ![](https://i.imgur.com/qs1VgWr.gif) ### 配合responsive layout 但是...在我把網頁縮小後就出事了,網頁排版能跟著視窗大小調整但動畫的起始、結束點不行,因此就出現動畫卡住、動畫出不來或是閃現出來諸如此類的bug ![](https://i.imgur.com/XgtCjPW.gif) 然後在不停找資料後,只有找到xPercent, yPercent等好像沒有在GSAP 3用的東西,最後甚至跑去stack overflow問大佬XD,但有點溝通障礙,果然我問問題的方法還是太拙劣了,一開始還忘了放codepen 最後回到youtube意外找到start, end用method寫的方法,終於解決這問題 ```javascript= const computer = document.querySelector(".hobby-image"); for(hobbyElement of hobbyElements) { gsap.from(`.${hobbyElement.name}`, { scrollTrigger: { trigger: `.${hobbyElement.name}`, start: () => `top ${window.screen.availHeight * 0.4 + computer.offsetTop * 0.8}`, //原本的視窗40% + 80%電腦離容器頂端的距離來因應文字跑到上方的情況 end: () => `+=${computer.getBoundingClientRect().height * 0.3}`, // 動畫結束改設為起始點以下30%電腦高度 scrub: true, toggleActions: "restart pause reverse pause" }, opacity: 0, duration: 1.5, x: hobbyElement.x, y: hobbyElement.y }); } ``` 這樣酷酷的動畫就能在各種視窗大小觀賞了 ![](https://i.imgur.com/bU7n4GM.gif) 個人照的動畫就如法炮製就好,喔耶~ ```javascript= const imageScrollFunction = () => { const image = document.querySelector(".my-image"); gsap.from(".personal-photo", { scrollTrigger: { trigger: ".personal-photo", start: () => `top ${window.screen.availHeight * 0.3 + image.offsetTop * 0.8}`, toggleActions: "restart pause reverse reverse", }, ease: "expo.out", //劇烈漸慢 clipPath: "polygon(0 100%, 100% 100%, 100% 100%, 0 100%)", //裁切 y: 50, duration: 3 }); } ``` 個人照的動畫不用像電腦一樣那麼複雜,改成用裁切展開的特效 ![](https://i.imgur.com/AVjVwcT.gif) 順帶一提,照片裡那隻是我們校狗,他叫大黑 ## 小小的結語 寫動畫真的挺好玩的,雖然中間debug的時候真的讓我很頭痛,下一篇就是navbar~ --- <ul style ="display: flex; flex-direction: row; width: 100%; justify-content: space-between;margin: 0; padding: 0;"> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/BkCAZwj_Y" >上一篇</a></li> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/rJBpwRsut">主頁</a></li> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/Bysh-oH5K">下一篇</a></li> </ul>