###### tags: `Vue` `店商網頁` {%hackmd BJrTq20hE %} # Vue店商網頁-首頁主視覺效果 會想要寫出最終作業的主視覺最主要的原因是看到了[Line主視覺動畫效果](https://www.youtube.com/watch?v=GWmHLZtX-pk),你看都直接有影片可以看了,最差就是照著寫一定很快就可以寫出來了,但是事情不是笨蛋所想的那麼簡單,那個笨蛋就是我。 首先分析動畫效果: 1.螢幕往下滑動時banner製中縮小 2.banner的圖片會不停切換 ## 螢幕往下滑動時banner製中縮小 這裡的想法是監控螢幕的scrollY值,當Y值大於某個數字之後就把banner縮小製中。 下面是關鍵程式碼,最主要是利用:class="{}" 見下面例子的html第1、2行。 JS ```javascript= methods: { scrollWatch () { // 取得scrollY數值 this.scrollY = window.scrollY } }, mounted () { // 監聽scroll window.addEventListener('scroll', this.scrollWatch) } ``` html ```htmlembedded= <div class="frame d-flex justify-content-center align-item-center position-relative" :class="{ 'frame-short':scrollY > 10 }"> <ul class="bannerGroup px-0" :class="{ 'banner-center': scrollY > 10 }" ref="BannerImages"> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===0}" style="background-image:url(https://upload.cc/i1/2022/03/26/VEKZkG.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===1}" style="background-image:url(https://upload.cc/i1/2022/03/26/hdM1VB.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===2}" style="background-image:url(https://upload.cc/i1/2022/03/27/bytXzS.jpg)"></li> <li class="bannerSpecial d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===3}" style="background-image:url(https://upload.cc/i1/2022/03/27/GMxio4.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===4}" style="background-image:url(https://upload.cc/i1/2022/03/27/7urNmk.jpg)"></li> </ul> </div> ``` SCSS ```sass= .banner-center { position: absolute; top: 100px; transition: all 0.5s; width: 80%; height: 60%; } .frame { min-height: 100vh; transition: all 0.5s; } .frame-short { min-height: 50vh; transition: all 0.5s; } ``` ## banner的圖片會不停切換 ### 1.如果只是兩張圖片切換那只要純CSS就可以達成,範例如下。 運作原理是用兩張圖片淡出到淡入,其中第二張圖片執行的時間點是第一張圖片的動畫效果執行到一半時開始執行動畫效果,最後就會相互疊成兩張圖片輪播的效果,關鍵程式碼是第29行的animation-delay: SCSS ```css= $animationBannerSecond:16s; .banner { position: absolute; top: 0; background-image: url(https://upload.cc/i1/2022/03/26/VEKZkG.jpg); width: 100%; height: 100%; background-repeat: no-repeat; background-size:cover; transition: all 0.5s; animation:bannerCarousel; animation-duration: $animationBannerSecond; animation-timing-function: ease-in; animation-iteration-count: infinite; } .banner2 { position: absolute; top: 0; background-image: url(https://upload.cc/i1/2022/03/26/hdM1VB.jpg); width: 100%; height: 100%; background-repeat: no-repeat; background-size:cover; transition: all 0.5s; animation:bannerCarousel; animation-duration: $animationBannerSecond; animation-timing-function: linear; animation-iteration-count: infinite; animation-delay: $animationBannerSecond * 0.5; } @keyframes bannerCarousel { 0% { opacity: 100%; } 25% { opacity: 50%; } 40% { opacity: 0%; } 60% { opacity: 0%; } 75% { opacity: 50%; } 100% { opacity: 100%; } } } ``` ### 2.如果要3張圖片以上切換就需要加入JS去控制每張圖片出現的時間。 1.imgLen為圖片有多少張,這裡是透過在html標籤內使用ref見下方範例html第1行命名,取得ul內容長度見下方範例JS第17 2.使用setInterval()控制每張圖片動畫開始執行的間隔時間。因為setInterval用的單位是毫秒所以animationDuration是秒數*1000。見下方範例JS第5行,整個動畫效果時間淡入加上淡出時間為6秒,所以每隔3秒就要執行一次動畫,並透過animationAction % imgLen的餘數控制bannerAnimation是否載入見下方範例html第二到六行。 3.所有圖片預設opacity為0見下方範例SCSS第二行,本身也是淡出效果,如果不預設為透明就只會看到最後的兩張圖片互相交換而已。 4.把所有ul圖片疊在一起見下方範例SCSS第六行。 5.淡出動畫效果見下方範例SCSS第二十行。 JS ```javascript= data () { return { animationAction: 0, imgLen: 0, animationDuration: 3000 } } methods: { runAnimation () { setInterval(() => { this.animationAction += 1 }, this.animationDuration) } } , mounted () { this.imgLen = this.$refs.BannerImages.children.length this.runAnimation() } ``` html ```htmlembedded= <ul class="bannerGroup px-0" :class="{ 'banner-center': scrollY > 10 }" ref="BannerImages"> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===0}" style="background-image:url(https://upload.cc/i1/2022/03/26/VEKZkG.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===1}" style="background-image:url(https://upload.cc/i1/2022/03/26/hdM1VB.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===2}" style="background-image:url(https://upload.cc/i1/2022/03/27/bytXzS.jpg)"></li> <li class="bannerSpecial d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===3}" style="background-image:url(https://upload.cc/i1/2022/03/27/GMxio4.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===4}" style="background-image:url(https://upload.cc/i1/2022/03/27/7urNmk.jpg)"></li> </ul> ``` SCSS ```css= $animationDuration:6s; .d-none-slow{ transition: all $animationDuration; opacity: 0; } .bannerGroup { position: relative; width: 100%; li { list-style: none; position: absolute; top: 0; width: 100%; height: 100%; background-repeat: no-repeat; background-size:cover; background-position:center center; } } .bannerAnimation { transition: all $animationDuration; opacity: 1; } ``` ### 3.位什麼不用@keyframs做淡出效果呢? 一開始的確是使用@keyframs做效果,但是不知道什麼原因在gitHubPage上的chrom與edge上圖片漸入漸出的效果不會執行,但是在Firefox與Safari則沒有問題。 [出問題的github版本連結](https://github.com/a121515222/Vue-seventh-week/tree/1efc230e0cac48539008571634918bb2b3d98ff0) ### 4.最後把所有效果集合起來的程式碼 [整份作業的github連結](https://github.com/a121515222/Vue-seventh-week) html [視覺效果的github連結](https://github.com/a121515222/Vue-seventh-week/blob/main/src/views/HomeView.vue) ```htmlembedded= <div class="container-fluid pt-7 px-0"> <div class="frame d-flex justify-content-center align-item-center position-relative" :class="{ 'frame-short':scrollY > 10 }"> <ul class="bannerGroup px-0" :class="{ 'banner-center': scrollY > 10 }" ref="BannerImages"> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===0}" style="background-image:url(https://upload.cc/i1/2022/03/26/VEKZkG.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===1}" style="background-image:url(https://upload.cc/i1/2022/03/26/hdM1VB.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===2}" style="background-image:url(https://upload.cc/i1/2022/03/27/bytXzS.jpg)"></li> <li class="bannerSpecial d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===3}" style="background-image:url(https://upload.cc/i1/2022/03/27/GMxio4.jpg)"></li> <li class="d-none-slow" :class="{'bannerAnimation': animationAction % imgLen ===4}" style="background-image:url(https://upload.cc/i1/2022/03/27/7urNmk.jpg)"></li> </ul> </div> </div> ``` JS ```javascript= data () { return { scrollY: 0, animationAction: 0, imgLen: 0, animationDuration: 3000 } }, methods () { runAnimation () { setInterval(() => { this.animationAction += 1 }, this.animationDuration) }, scrollWatch () { // 取得scrollY數值 this.scrollY = window.scrollY } }, mounted () { // 監聽scroll window.addEventListener('scroll', this.scrollWatch) this.imgLen = this.$refs.BannerImages.children.length this.runAnimation() } ``` CSS ```css= $animationDuration:6s; .d-none-slow{ transition: all $animationDuration; opacity: 0; } .bannerGroup { position: relative; width: 100%; li { list-style: none; position: absolute; top: 0; width: 100%; height: 100%; background-repeat: no-repeat; background-size:cover; background-position:center center; } } .bannerAnimation { transition: all $animationDuration; opacity: 1; } .banner-center { //監測到scrollY的值大於設定值時 使用這個效果 position: absolute; top: 100px; transition: all 0.5s; width: 80%; height: 60%; } .frame { min-height: 100vh; transition: all 0.5s; } .frame-short { min-height: 50vh; transition: all 0.5s; } ```