Parallax Scrolling 網頁視差滾動製作方法
網頁開發Parallax Scrolling 是指當您在滾動網頁時,讓特定元素以不同的速度移動,創造出一種視覺上的效果,稱為視差滾動。 這種技術能讓您的網站看起來更豐富、更時尚感、更具沉浸感,使用視差滾動製作的網頁,您很難不被它吸引。 該技術在早期的 Flash 動畫就已經很常見了,直到 2010 年之後才開始在網頁設計中出現。
直接來看看一些例子,可能會更有感覺。
看完後,是不是很吸引眼球呢? 上述網站要製作的困難度非常高,可以直接另開專案處理了。 而本文將介紹兩種相對簡單很多的方法,讓您的網站可以輕鬆使用。
方法一:使用 background-attachment: fixed
CSS background-attachment: fixed; 使用方法簡單,甚至完全不用使用到 JavaScript 就能實現。 雖然無法製作出太複雜的場景,但由於方法簡單,使用非常廣泛,在很多網頁中都能看得到,非常值得一學。
以下範例,我使用四張圖片,並在圖片正中央顯示圖片來源文字。 在移動卷軸的過程中,如果圖片碰到視窗最上方時,就將圖片 background-attachment 設定為 fixed,這樣就能實現最基本的視差滾動效果。 HTML 結構大致如下:
<div class="parallax">
<div class="layer">
<div class="text">Photo by Nathan Anderson on Unsplash</div>
</div>
<div class="layer">
<div class="text">Photo by Alyssa Boobyer on Unsplash</div>
</div>
<div class="layer">
<div class="text">Photo by eberhard grossgasteiger on Unsplash</div>
</div>
<div class="layer">
<div class="text">Photo by Denis Degioanni on Unsplash</div>
</div>
</div>
CSS 的重點是圖片必需用 background-image 載入,其他只是一些排版的 CSS 設定而已,可以根據自己的需求調整。
.parallax {
width: 100%;
overflow: hidden;
}
.parallax .layer {
width: 100%;
height: 100vh;
position: relative;
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
}
.parallax .layer:nth-child(1) {
background-image: url(1.jpg);
}
.parallax .layer:nth-child(2) {
background-image: url(2.jpg);
}
.parallax .layer:nth-child(3) {
background-image: url(3.jpg);
}
.parallax .layer:nth-child(4) {
background-image: url(4.jpg);
}
.parallax .layer .text {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
padding-top: 30vh;
font-size: 3rem;
color: #FFFFFF;
}
最後是 JavaScript 的部分,只要偵測到圖片碰到視窗最上方時,就將 background-attachment 設定為 fixed。
window.addEventListener('load', (event) => {
const layers = Array.from(document.querySelectorAll('.layer'));
window.addEventListener('scroll', (event) => {
const scrollPositionY = this.pageYOffset;
layers.forEach(layer => {
layer.style.backgroundAttachment = scrollPositionY > layer.offsetTop ? 'fixed' : '';
});
})
})
-
行 5:
this.pageYOffset 可以取得目前捲軸位置。 -
行 7:
layer.offsetTop 可以取得圖片距離網頁頂部的距離,藉由判斷 offsetTop 與 pageYOffset 的數值大小,就能知道圖片是否碰觸到視窗頂部。
方法二:使用各種 transform
方法一的做法只能製作一些比較簡單的視差滾動,如果要製作複雜版本的話,就需要在使用者移動卷軸時,搭配各種 transform 來實現視差滾動,這也是比較常見的做法。 以下是比較常見的 transform 方法:
- translate() 平移
- scale() 縮放
- rotate() 旋轉
- skew() 歪斜
接續方法一的例子,修改成當使用者移動卷軸時,使用 translateY() 讓圖片往上移動變慢,並透過 scale() 讓中間的文字從沒有顯示慢慢放大。 為了實現這個效果,需要先在 CSS 中將文字縮放至最小,並將 padding-top 設定為 30vh。 這樣在捲動時,效果會比較好,30vh 只是一個大概的數值,您可以嘗試使用其他數值來讓效果更好。
.parallax .layer .text {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
padding-top: 30vh;
font-size: 3rem;
color: #FFFFFF;
// 加入這兩行
transform: scale(0);
padding-top: 30vh;
}
JavaScript 的部分,必須盡可能地減少在 scroll 事件中操作 DOM 元素,大致上邏輯與方法一雷同,修改 JavaScript 如下:
window.addEventListener('load', (event) => {
const layers = Array.from(document.querySelectorAll('.layer'));
const texts = layers.map(layer => layer.querySelector('.text'));
window.addEventListener('scroll', (event) => {
const scrollPositionY = this.pageYOffset;
for (let i = 0; i < 4; i++) {
const layer = layers[i];
const text = texts[i];
const offsetTop = layer.offsetTop;
if (scrollPositionY > offsetTop) {
layer.style.transform = `translateY(${(scrollPositionY - offsetTop) * 0.5}px)`;
text.style.transform = `translateY(${(scrollPositionY - offsetTop) * -0.5}px) scale(${((scrollPositionY - offsetTop) / layer.clientHeight) * 2})`;
} else {
layer.style.transform = '';
text.style.transform = '';
}
}
})
})
-
行 6:
this.pageYOffset 可以取得目前捲軸位置。 -
行 12:
藉由判斷 layer.offsetTop 與 pageYOffset 的數值大小,就能知道圖片是否碰觸到視窗頂部。 -
行 13:
根據以下公式並透過 translateY() 調整圖片的位移量,在上方範例中,將 speed 設定為 0.5,所以圖片會比正常還要慢一半的速度往上移動。
位移公式 = (this.pageYOffset - layer.offsetTop) * speed
speed 為 0 表示圖片不會有任何位移,也就是正常捲軸移動圖片跟著移動的模式。
speed 為 1 表示圖片位移量等於捲軸位移量,也就是圖片會被釘在原地,不會跟著捲軸移動。
-
行 14:
與行 13 使用相同方法,只是讓文字往反方向移動,不然如果再加上縮放的話,看起來文字會往下跑。接著再搭配以下公式,並使用 scale() 讓文字縮放,在上方範例中,將 speed 設定為 2,所以文字最終會放大到原來的兩倍。
縮放公式 = ((this.pageYOffset - layer.offsetTop) / layer.clientHeight) * speed
speed 為 0 表示文字不會縮放,所以會一直看不到文字。
speed 為 1 表示文字會放大到 CSS 中,font-size 設定的文字大小。
speed 為 2 表示文字會放大到 CSS 中,font-size 設定的文字大小的兩倍。
結語
製作較複雜的視差滾動效果需要計算各種數值,雖然基本原理都是根據卷軸位置與各種 transform 來實現,但我認為製作難度仍然很高,本文介紹的兩種方式已經是非常簡單的方法了。 如果大家實作上有遇到什麼困難的話,歡迎留言討論喔。
0 則留言