脫離 library 後需要自己解決的問題
該怎麼偵測頁面滾動?
在 window 上監聽 scroll event?基本上不可行,scroll event 被呼叫的太過頻繁,網頁會變很頓,既然如此那我們就要想辦法避開這個問題,最直覺的解法就是 setTimeout/setInterval,但是這還是不夠完美,依然會造成過度重繪問題。比較好的作法是使用 requestAnimationFrame,使用 requestAnimationFrame 後瀏覽器會依據這個網頁是不是當前 tab 等資訊來作適當的資源分配,網頁會非常滑順!詳細的規格可以閱讀 w3c 文件 或 mdn,遇到較舊瀏覽器的時候才使用 setTimeout。
var requestAnimationFrame = (function () {
return window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.msRequestAnimationFrame
|| setTimeout;
})();
還可以搭配 scroll event 來判斷是否要啟動 loop,當在同一個位置停留兩次後暫停 loop(cancelAnimationFrame),捲動事件觸發後開始 loop。
Transition
transition 也是一個問題,要先了解自己的需要,像是我預期我自己大部分情況下網頁會有 ”區塊性”,每個區塊通常只表達一件事,區塊間的關連性可能也不高,所以我的想法就是把網頁分成數個區塊,然後獨立處理自己的 Transition,依據這個想法,當我在區塊一的時候我知需要知道我在區塊一的瀏覽進度,而且不需要精準到 px,其他區塊也完全可以忽略,不需要更新他們內部任何 element 的 css。其實依照我目前個人的觀察,這種作法應該可以解決 80% 以上的是差滾動網頁所需要辦到的事情,因為很少會出現一個跨區塊的物件,就算出現也可以接力完成,而且個人覺得這樣在寫程式時也比較方便,可以一眼知道目前畫面有哪一些東西會有動作。
該怎麼讓套用 css 變簡單?
我想我對簡單的定義是說我不打 prefix,也不要把 css 寫在 html,我要看到真實的程式碼,但是又有比較統一的寫法,有點囉唆 XD。
section.transitions([
{key: 'opacity', start: 0, end: 50, from: 0, to: 1, format: '%s'}
]);
給一個 css 屬性名稱然後設定他從幾 % ~ 幾 % 要處理這個 transition,還有開始與結束的值,format 是用來設定最後 css 屬性值的格式用的,主要是解決不同單位還有 transform 的問題,transform 寫法如下,values 裡面所計算出來的值案順序對應後面的 %s。
{key: 'transform', prefix: true, start: 0, end: 50, values: [from: 0, to: 90}, {from: 1, to: 1.5}], format: 'rotateX(%sdeg) scale(%s)'}
思考完該讓 api 長什麼樣子之後接著就是實作,這裡主要會遇到的問題是 prefix,如果把所有主流瀏覽器的 prefix 全部加上感覺真的很蠢,應該是網頁載入後我們去偵測瀏覽器 prefix 然後每次更新 css 的時候只加這個 prefix,那要怎麼偵測呢?我們會到 getComputedStyle 這個 function 來取得所有的 css 屬性名稱還有值,他取得的資料是真的套用於被傳入的 element 上的 css,包含瀏覽器預設,所以通常都可以看到我們所需要的 prefix 在裡面,下面這是我的作法。
var style = window.getComputedStyle(document.documentElement);
var match = Array.prototype.join.call(style, '').match(/-(?:o|moz|webkit|ms)-/i);
var prefix = match && match[0];
補充
Email me when Po-Ying Chen publishes or recommends stories
