Parallax Scrolling on Jinyong Campaign Page

http://jinyong.tw/

The Parallax Scrolling effect is presented in the campaign page of “Jinyong Collection” by moving the background layers on the horizontal axis. Frankly speaking, the website performance is not good enough, but I’m still going to share the production process, hope that it can bring more discussion!

The topic is separated into 5 parts,
1. Get start — web page planning and design
2. Use JQuery + CSS3 to create simple parallax scrolling effect
3. Use CSS3 to create the same effect
4. Optimize the load time
5. Trigger horizontal scrolling when scrolling down

這次《 金庸作品集 — 復刻典藏版 》開賣 Landing Page ,在畫面採用橫軸的移動,分圖層配合視差滾動;可以很坦誠這次並沒有把效能處理好,但還是分享一下製作經過,藉此拋磚引玉!

這次主題分成:
1. 畫面規劃解說
2. 使用 JQuery + CSS3 製作簡單的視差
3. 使用純 CSS3 製作相同效果(但 Safari 及 FireFox 有些問題尚未解決 )
4. 簡單處理圖片載入,提升使用者體驗
5. 簡易製作「向下滾動 / 滑動」觸發「水平滾動 / 滑動」

Web Page Planning

Before I start coding, I exported the images as the example above. The way the layers move is presented below.

在切版前,我將圖層輸出如上,在 CSS 上會相當好定位,可以稍微了解視差方式會如下圖

Use JQuery + CSS3 To Create Simple Parallax Scrolling Effect

When scrolling down the page, the certain amount of scrolling will be detected to change the position of the layers.

當頁面滑動時,去偵測「滑動的多少 」,利用這個值去改變圖層位置

$('header').bind('scroll', function(){
var sl = $(this).scrollLeft();
var z2 = sl/ 20
var z3 = sl/ 6.2
var z4 = sl/ 5
var z5 = sl/ 3
var z6 = sl/ 2.7
var z7 = sl/ 2.4
$('#screen-z2').css('transform','translate3d(' + z2 + 'px,0,0) scale(1)')
$('#screen-z3').css('transform','translate3d(' + z3 + 'px,0,0) scale(.9)')
$('#screen-z4').css('transform','translate3d(' + z4 + 'px,0,0) scale(.85)')
$('#screen-z5').css('transform','translate3d(' + z5 + 'px,0,0) scale(.8)')
$('#screen-z6').css('transform','translate3d(' + z6 + 'px,0,0) scale(.8)')
$('#screen-z7').css('transform','translate3d(' + z7 + 'px,0,0) scale(.8)')
})

Explaination
1. You can bind an ‘scroll’ event on <header> to change your ‘sl’ value defined by ‘$(‘header’).scrollLeft()’
2. Use ‘sl’ to adjust the position of layers ‘translateY(sl)’
3. Why adding ‘scale()’? I just want to make it seem more real, it’s not necessary
4. How do you define z1, z2, …, z7? I actually adjust them according to the speed provided by the animator. These are not standard settings.

1.在 header 註冊一個 scroll 事件,每當這事件發生就會重新抓取$(‘header’).scrollLeft() 的值
2. 利用 $(‘header’).scrollLeft() 變化的值去持續改變每一個圖層的位置
3. 為何加上 scale() 屬性?只是為了添加一點立體感,可以忽略
4. z1、z2 …. z7 這些怎麼定義而來的?其實就是按照動畫師提供的速度調整,這也不是絕對設定

Use CSS3 to Create The Same Effect

Convert the whole page into 3D layers rendered from the perspective. The Z-axis translation of the layers creates a natural parallax rolling effect.

將整個畫面轉成 3D 圖層,利用「透視」,並把圖層做 Z 軸的位移,做出接近自然的視差滾動

header { perspective: 10px; }
.screen-box { transform-style: preserve-3d; }
#screen-z1 { z-index: 7; transform: translate3D(0,0,0px)     scale(1);    }
#screen-z2 { z-index: 6; transform: translate3D(-1%,3%,-1px) scale(1.04); }
#screen-z3 { z-index: 5; transform: translate3D(-2%,6%,-2px) scale(1.08); }
#screen-z4 { z-index: 4; transform: translate3D(-3%,9%,-3px) scale(1.12); }
#screen-z5 { z-index: 3; transform: translate3D(-4%,12%,-4px)scale(1.16); }
#screen-z6 { z-index: 2; transform: translate3D(-5%,15%,-5px)scale(1.2);  }
#screen-z7 { z-index: 1; transform: translate3D(-6%,18%,-6px)scale(1.24); }

Explanation
1. Due to perspective effect and Z-axis translation, the layers will look relatively small (like when you look at distant buildings, the farther the smaller you see), then you must use the scale property to magnify the layer back to normal size.
2. ‘translateX()’ and ‘translateY()’ is only used to correct the visual position.

1.因透視效果 + Z 軸位移,故圖層會看起來比較小(就好比看遠方建築物,越遠越小),這時就必須用 scale 屬性加圖層放大回來。
2. translate 的 X 軸及 Y 軸位移也只是為了將圖視覺位置校正,其實也是很土炮地用肉眼調整的

‘Overflow: hidden’ In Different Browsers

No matter which approach you use, you may want to use the css property ‘overflow: hidden’ to cut the off-screen part, for example:

無論是用上述何種方式,我們不免俗會使用 overflow: hidden 去切除超出的部分,如下圖

However, if you only use CSS to create the 3D effect, there is a problem: ‘overflow : hidden’ has different definitions in different browsers

  • Chrome:Renders perfectly. The image won’t exceed the page and presents the CSS parallax effect
  • Safari & FireFox:’overflow: hidden’ will turn the layers form 3D back to 2D, the parallax effect won’t work

Therefore, I choose to control it with JQuery at last. Please share with me if you have a better solution!

但這時,如果你使用的是純 CSS 的 3D 效果,overflow 在各瀏覽器會有不一樣的詮釋方式:
・Chrome:完美呈現,圖不會超出,又有純 CSS 的視差效果
.Safari & FireFox:overflow 會將圖層壓回 2D ,頓時失去視差效果
也因如此,最後還是選擇搭配 JQuery 去控制,如果各位有更好的做法歡迎指教!

Load The First Screen Which The Users Will See

This is actually not a specialized skill, but a way of thinking. The users will see the image loading on the first screen; the rest of the images will start loading after JavaScript events binding. I’ll show you how to simply do this.

這其實不是一個專有的技巧,只是一種設計思維;方法只是將使用者會優先看到圖片載入,剩下的等 JavaScript 執行完,再慢慢載入其他圖片,確保跟使用者操作有關的事件都已註冊完畢。我來介紹我如何簡單做出這件事!

<img class="screen-1" src="/assets/img/main/bg/1-z1.png">
<img class="screen-2" src="/assets/img/main/bg/2-z1.png">
<img class="screen-3 load" data-src="/assets/img/main/bg/3-z1.png">
<img class="screen-4 load" data-src="/assets/img/main/bg/4-z1.png">
<img class="screen-5 load" data-src="/assets/img/main/bg/5-z1.png">
<script>
// 將此程式碼放在所有 js 最後面
$(".load").each(function(){
var s = $(this).attr('data-src')
$(this).attr("src", s)
})
</script>

Explanation
1. Remove the ‘src’ attribute of the <img> , and set a custom property ‘data-src’ according to its source (you can also name it “data-xxxxx”)
2. When finishing all the JavaScript execution, the images will start loading at last. This way, the users won’t need to wait for such a long time, and it can also ensure all events binding

1.將一開始看不到的 img 去掉 src 屬性,並將其圖片位置給予一個自定義屬性 data-src( 也可以取名叫做 data-xxxxx )
2.當執行完所有關於操作的 js 時,最後再用 JQuery 改變 src ( 根據其 data-src 值 )

How To Trigger Horizontal Scrolling When Scrolling Down

In fact, this is done by converting the value of vertical rolling into the value of horizontal rolling. Check out this article for more details: https://css-tricks.com/snippets/jquery/horz-scroll-with-mouse-wheel/

It is worth mentioning that there is actually a gap between the rolling speed on Windows and Mac OS, so you can use the ‘userAgent’ to calculate them separately.

if(navigator.userAgent.indexOf("Window")>0) {
$("header").mousewheel(function(event, delta) {
this.scrollLeft -= delta * 35;
event.preventDefault();
})
}
else if(navigator.userAgent.indexOf("Mac OS X")>0) {
$("header").mousewheel(function(event, delta) {
this.scrollLeft -= delta;
event.preventDefault();
})
}

其實就是將上下滾動的值,轉換成左右滾動的值,可直接參考 此文章
值得一提,在 Windows 跟 OS ,滾動的速度其實有落差,這時候就可以利用 ‘userAgent’ 去做不一樣的計算,程式碼如上

下一篇!用 Vue.js 打造你的客製化兔兔
Next Article: Building Your Own Customized Rabbit With Vue.js. To be continued!