毋須編寫 JavaScript,建立頁面捲動動畫。
有時候我們想因應頁面捲動的位置建立動畫,或更新 HTML 元素的 CSS 樣式。就像影片播放一樣,動畫在頁面向上捲動時前進,向下捲動時後退。
使用 Trigger JS,在頁面捲動時即可透過 CSS 變數取得製作動畫所需的值,而毋須編寫任何 JavaScript 代碼,相關設置則可透過 HTML 屬性實現。點擊這裡查看範例。
閱讀本文檔的其他語言版本:English、繁體中文、简体中文。
-
透過 script 標籤將 trigger.js 加載到網頁中:
- UNPKG CDN:
<script src="//unpkg.com/@triggerjs/trigger" defer></script>
- jsDelivr CDN:
<script src="//cdn.jsdelivr.net/npm/@triggerjs/trigger" defer></script>
-
為對應的 DOM 元素加上
tg-name屬性,設定值等於接收數值的 CSS 變數名。
<div tg-name="scrolled" id="greeting">Hello, World</div>上述例子中,CSS 變數 --scrolled 會被加入到 #greeting 選擇器中:
<style>
body {
padding: 100vh 0; /* 確保頁面有足夠空間捲動 */
}
#greeting {
transform: translateX(calc(var(--scrolled) * 1px)); /* 轉換為 px 單位 */
}
</style>- 捲動頁面,測試效果。
- 從以下任一途徑獲取原始碼:
- GitHub
git clone https://github.com/triggerjs/trigger.git
- NPM
npm i @triggerjs/trigger
- 切換到目錄內,安裝依賴:
npm install
- 本身已經有一個預打包的版本在
dist/bundle.js。運行一個本地網頁伺服器,查看範例歡迎頁index.html:- 例如透過運行
npx serve - 在瀏覽器中打開
http://localhost:5000 - 捲動頁面,測試效果。
- 例如透過運行
- 以下指令會打包一個新的版本到
dist/bundle.js:- 開發環境版本(持續監聽修改):
npm run watch
- 開發環境版本:
npm run build
- 生產環境版本:
npm run prod
- 開發環境版本(持續監聽修改):
| 屬性名稱 | 類型 | 預設值 | 簡介 |
|---|---|---|---|
tg-name |
必填 | - | 接收捲動值的 CSS 變數名稱,是否加上 -- 前綴都可。 |
tg-from |
選填 | 0 |
起始值 |
tg-to |
選填 | 1 |
終點值 |
tg-steps |
選填 | 100 |
從 tg-from 至 tg-to 之間觸發多少次 |
tg-step |
選填 | 0 |
每次遞加的數值,如果此值不為 0,則會忽略 tg-steps 的設定。 |
tg-map |
選填 | (空白字串) | 將一個值映射至另一個值。格式: - 一個值映射至另一個值: value: newValue; value2: newValue2- 多個值映射至另一個值: value,value2,value3: newValue- 一個範圍映射至另一個值: value...value2: newValue |
tg-filter |
選填 | (空白字串) | 只當捲動值在列表當中時才觸發,格式:1,3,5,7,9。預設情況下,過濾模式是 retain(保留值),在設定值末端加入 ! 符號可以將模式切換為 exact(絕對)。關於兩個模式的分別,請參考後續的內容。 |
tg-edge |
選填 | cover | 計算捲動值的起始點與結束點。cover 代表畫面外至畫面外,即在元素從底部進入畫面時開始計算,從頂部完整離開畫面時結束;inset 代表當元素的頂部觸及頁面的頂部時開始計算,元素的底部觸及頁面的底部時結束。以下將有圖解說明。 |
tg-follow |
選填 | (空白字串) | 引用其他元素的計算值。tg-follow 的設定值等於目標元素的 tg-ref 設定值。注意:當設定了 tg-follow,同一元素下的 tg-from、tg-to、tg-steps、tg-step 以及 tg-edge 設定會被忽略。 |
tg-ref |
選填 | (空白字串) | 定義可以被其他元素透過 tg-follow 引用的名稱。 |
tg-bezier |
選填 | (空白字符串) | 貝茲曲線設定,設定值為 ease、easeIn、easeOut、easeInOut 或自定義的貝茲曲線數值,格式是:p1x,p1y,p2x,p2y。 |
數字並不適用於所有情況。例如,我們希望在捲動頁面的時候更改文字顏色,這個時候 tg-map 屬性就派上用場了。
以下例子示範如何根據下表的規則更新文字顏色:
| 元素位置(從頁底起) | 捲動的值 | 文字顏色 |
|---|---|---|
| 0% - 10% | 1 | black |
| 10% - 20% | 2 | red |
| 20% - 30% | 3 | orange |
| 30% - 40% | 4 | yellow |
| 40% - 50% | 5 | green |
| 50% - 60% | 6 | cyan |
| 60% - 70% | 7 | blue |
| 70% - 80% | 8 | purple |
| 80% - 90% | 9 | grey |
| 90% - 100% | 10 | grey |
<h1
id="heading"
tg-name="color"
tg-from="1"
tg-to="10"
tg-steps="9"
tg-map="1: black; 2: red; 3: orange; 4: yellow; 5: green; 6: cyan; 7: blue; 8: purple; 9,10: grey"
>
彩虹文字
</h1>
<style>
body {
padding: 100vh 0; /* 確保頁面有足夠空間捲動 */
}
#heading {
color: var(--color);
}
</style>假設 tg-from="200" 以及 tg-to="-200",我們想透過 transform: translateX() 將一個元素在 x 方向移動。tg-steps 讓我們設定從 200 到 -200 總共有多少步,舉個例子,tg-steps="400" 等於用 400 步從 200 遞減到 -200,每一步等於 1;換句話說,tg-steps="800" 就代表每一步等於 0.5。
但是有些時候,我們不想自行運算,這就是 tg-step 出現的原因。tg-step 直接定義每一步的值,所以如果定義了 tg-step,tg-steps 就會被忽略。
有時我們只對某些特定的值感興趣。例如,我們只想知道從 0 至 100 (tg-from="0" 以及 tg-to="100") 之間,什麼時候出現 25, 50, 75。在這個情況中,tg-filter 就可以幫上忙。
<h1
id="heading"
tg-name="color"
tg-from="0"
tg-to="100"
tg-step="1"
tg-filter="25,50,75"
tg-map="25: red; 50: yellow; 75: green"
>
Red (25), Yellow (50), Green (75)
</h1>
<style>
body {
padding: 100vh 0; /* 確保頁面有足夠空間捲動 */
}
#heading {
color: var(--color);
}
</style>tg-filter 有兩個模式,預設是 retain,另一個設定值是 exact。為了更好的說明差異,請參閱以下例子:
<h1
id="heading"
tg-name="color"
tg-from="0"
tg-to="10"
tg-step="1"
tg-filter="5"
tg-map="5: blue"
>
Trigger.js
</h1>
<style>
body {
padding: 100vh 0; /* 確保頁面有足夠空間捲動 */
}
#heading {
--color: black;
color: var(--color);
}
</style>上述例子中,文字顏色初始是黑色,而將文字捲動到頁面中間時,會變為藍色。不過文字就永遠都不會變回黑色了,因為沒有讓它改變為黑色的觸發點。
如果我們想文字顏色只在計算值是 5 的時候改變為藍色,其他時候是黑色,可以將代碼更改為:
<h1
id="heading"
tg-name="color"
tg-from="0"
tg-to="10"
tg-step="1"
tg-filter="4,5,6"
tg-map="4: black; 5: blue; 6: black"
>
Trigger.js
</h1>這樣雖然可以,不過很快我們的代碼就變得冗長。為了解決這個情況,我們可以將模式切換為 exact,只須在 tg-filter 的末端加入 ! 符號即可:
<h1
id="heading"
tg-name="color"
tg-from="0"
tg-to="10"
tg-step="1"
tg-filter="5!"
tg-map="5: blue"
>
Trigger.js
</h1>在 exact 模式下,--color 只會在計算值等於 5 的時候設定為 blue,其他值的時候就變為預設值。
直接在 tg-filter 中加入 ! 符號這種設計,主要是考慮到這種需求應該只會在 tg-filter 中發生。如果又另外建立一個屬性來設定模式,可能會變得不需要甚至容易誤解。
就像一些 CSS 屬性一樣,tg- 屬性(除了 tg-follow,tg-ref)的值會繼承自父級元素(如果當前元素沒有設定的話)。如果不希望繼承父級元素的值,並設定為預設值的話,只需增加沒有值的 tg- 屬性即可。例如:
<div tg-name="scale" tg-from="0" tg-to="50">
<span tg-name="color" tg-to>
<!-- tg-to 現在的值是 1(預設值) -->
</span>
</div>cover(預設值)和 edge 的分別如下圖所示:
所以當 tg-edge="inset",元素的高度必須大於瀏覽器視窗(window.clientHeight)的高度。
我們也可監聽指定元素的 tg 事件來獲取值:
<h1
id="heading"
tg-name="color"
tg-from="1"
tg-to="3"
tg-steps="2"
tg-map="1:#000;2:#666;3:#ccc"
>
Trigger JS
</h1>
<style>
body {
padding: 100vh 0; /* In order to make the page have enough rooms for scrolling */
}
#heading {
color: var(--color);
}
</style>
<script>
document.querySelector('#heading').addEventListener('tg', (e) => {
console.log(e.detail); // {value: '#666'}
});
</script>假如你擔心 tg- 前綴可能不符合 HTML 5 的標準,可以透過在 body 標籤中加入 data-trigger-prefix 去自定義它:
<body data-trigger-prefix="data-tg">
<div data-tg-name="scrolled" id="greeting">Hello, World</div>
</body>上述例子中將前綴自定義為 data-tg。data-* 是完全符合 HTML5 標準的屬性,用於設置自定義的屬性和設定值。
歡迎 Fork 這個 Repo 進行開發,並提交 Pull Requests。在 GitHub Issues 回報 Bug,在 GitHub Discussions 討論功能/想法/問題。
Trigger.js 使用 MIT 授權.
