Velocity.js 動畫

特點

Velocity 與 jQuery 的 animate 使用方式一樣,但多了顏色、變形、轉場的動畫效果。這裡的版本為 1.5.2 版本,可參考官方網站文件,2.0.0 版本以上以 Github 版本文件為主,兩者文件本版不同,使用上也有些差異。Velocity 受 jQuery 影響,支援 Chain 串鏈方法。

使用方式

Velocity 可以配合 jQuery 或 JavaScript 這兩種寫法,一旦使用了 jQuery,另一種方式可能會失敗

jQuery + Velocity

velocity 配合 jQuery 時兩個參數都是物件,與 jQuery animate 參數使用方式一樣,一個是樣式物件,另一個是動畫參數物件

$(selector).velocity(STYLES,OPTIONS)

$(selector).velocity(
{
width: '500px',
property2: value2
},
{
/* Velocity's default options */
duration: 400,
delay: false,
easing: 'swing',
loop: false,
begin: undefined,
complete: undefined,
progress: undefined,
display: undefined,
visibility: undefined,
queue: '',
mobileHA: true
}
)

JavaScript + Velocity

使用函式方式,有三個參數,依序是 DOM 元素樣式物件動畫參數物件。DOM 元素為 getElement 系列或 querySelector 所選擇到的元素。

Velocity(DOM, STYLES, OPTIONS)

數值

$element.velocity({
top: 50, // Defaults to the px unit type
left: '50%',
width: '+=5rem', // Add 5rem to the current rem value
height: '*=2' // Double the current height
})

示範結構

Velocity 1.5.2 版本,注意的是,使用 jQuery 時,大寫 Velocity() 函式參數呼叫為 JavaScript 方式,您不能使用這種方法,而要改用$(selector).velocity()。

<style>
div {
top: 0;
left: 0;
width: 10%;
height: 100vh;
position: relative;
}

div:nth-child(1) {
background: #ff0000;
}

div:nth-child(2) {
background: #00ff00;
}

div:nth-child(3) {
background: #0000ff;
}

div:nth-child(4) {
background: #ffff00;
}
</style>
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
<div id="e"></div>

動畫參數物件設定(OPTIONS)

duration

與 jQuery 一樣支援 “slow”, “normal”, and “fast”。

$element.velocity({opacity: 1}, {duration: 1000})
$element.velocity({opacity: 1}, {duration: 'slow'})

delay

動畫延遲,以毫秒為單位。

  • JavaScript
Velocity(
document.querySelectorAll('div'),
{
opacity: 0,
tween: 100 // Optional
},
{
duration: 1000,
delay: 3000
}
)

easing

似乎不能使用 jQueryUI 或其他套件搭配字串的寫法,建議使用 bezier curve 的寫法,可參考 https://easings.net/。
第三個設定以[張力,摩擦]的形式傳遞兩個項目的陣列。較高的張力(默認值:500)會增加總速度和彈跳度。較低的摩擦力(默認值:20)會提高最終振動速度。

/* 似乎不能與 jQueryUI 配合 */
$element.velocity({width: 50}, 'easeInSine')
/* 使用貝茲曲線 */
$element.velocity({width: 50}, [0.17, 0.67, 0.83, 0.67])
/* [張力,摩擦] */
$element.velocity({width: 50}, [500, 20])
/* 產生步進動畫 */
$element.velocity({width: 50}, [8])

loop

設定動畫重複播放,值若為整數表示播放的交替次數(來回算一次),若為 true 表示無限循環,無限循環永遠不會返回 promise,確保在同一元素上只有一個無限循環(如果要使用另一個,必須停止前一個無限循環),可以使用 Velocity 參數 ‘stop’ 來停止。如果與 begin、complete 一起使用,begin、complete 分別在循環動畫的開始和循環動畫的結尾。不會為每個循環交替重新觸發它們。

begin 與 complete

beging 為當動畫「開始」時要執行的回呼函式。
complete 為當動畫「結束」時要執行的回呼函式。

兩者對多個元素進行了動畫處理時,只會回調執行一次。此外,如果循環調用,則回調僅觸發一次,也就是在第一個循環交替開始時,或在最後一個循環交替結束時。回調將整個原始 DOM(不是 jQuery 物件)元素作為其上下文和第一個參數傳遞。要單獨訪問這些元素,必須使用 jQuery 的$ .each()或 JavaScript 的.forEach()遍歷陣列。

  • jQuery 的 begin 寫法
$('div').velocity(
{
opacity: 0
},
{
duration: 2000,
begin: function (elements) {
console.log('動畫開始了', elements)
}
}
)
  • JavaScript 的 complete 寫法
Velocity(
document.querySelectorAll('div'),
{
opacity: 0
},
{
duration: 2000,
complete: function (elements) {
console.log('動畫開始了', elements)
}
}
)

progress

將進度選項傳遞給回調函數,以便在整個動畫過程中重複觸發該回調函數。回調函數將傳遞有關呼叫狀態的數據。此數據可用於自定義補間等。

elements: 回傳一個原始 JavaScript DOM 陣列元素。要單獨訪問這些元素,必須使用 jQuery 的$ .each()或 JavaScript 的.forEach()遍歷。
complete: 呼叫完成百分比(十進位顯示,乘以 100 可以表示 0~100%)。
remaining:剩餘多少時間直到呼叫完成(以毫秒為單位)。
start:呼叫開始的絕對時間(以 Unix 時間為準)。
tweenValue:補間動畫屬性的當前值,可以選擇將其傳遞到 Velocity 調用中。傳遞補間動畫屬性允許您隨後通過進度回調捕獲補間進度的確切值。與所有其他 Velocity 動畫屬性一樣,該屬性也受調用的 easing 行為影響tween 可以在樣式物件裡面自定義,以便為任意 DOM 屬性的變化設置動畫。

  • JavaScript 範例
Velocity(
document.querySelectorAll('div'),
{
opacity: 0
tween: 1000 // Optional
},
{
progress: function (elements, complete, remaining, start, tweenValue) {
console.log(complete * 100 + '%')
console.log(remaining + 'ms remaining!')
console.log('The current tween value is ' + tweenValue)
}
}
)

display 與 visibility

可以在動畫執行結束後 動態設定元素的 css 屬性 display 或 visibility。display 設定值以 CSS 為主。當使用 reverse 方向動畫指令時,display 和 visibility 選項都將被忽略。

  • JavaScript
/* 動畫結束後 元素 display 屬性設為 "none" */
Velocity(
document.querySelectorAll('div'),
{
opacity: 0
},
{
duration: 1000,
delay: 3000,
display: 'none'
}
)

/* 動畫結束後 元素的 visibility 屬性設為 hidden */
$element.velocity({opacity: 0}, {})
Velocity(
document.querySelectorAll('div'),
{
opacity: 0
},
{
duration: 1000,
delay: 3000,
visibility: 'hidden'
}
)

deqeue

設定動畫的佇列。注意,loop 迴圈選項 和 reverse 反向動畫指令,不能和佇列一起使用。

  • jQuery
$('div').eq(0).velocity({translateX: '50%'}, {queue: 'a'})
$('div').eq(1).velocity({translateX: '50%'}, {queue: 'b'})
$('div').eq(2).velocity({translateX: '50%'}, {queue: 'c'})
$('div').eq(3).velocity({translateX: '50%'}, {queue: 'd'})

setTimeout(function () {
$('div').eq(0).dequeue('a')
}, 1000)
setTimeout(function () {
$('div').eq(1).dequeue('b')
}, 2000)
setTimeout(function () {
$('div').eq(2).dequeue('c')
}, 3000)
setTimeout(function () {
$('div').eq(3).dequeue('d')
}, 4000)
  • JavaScript
setTimeout(() => {
Velocity(document.querySelector('#a'), {left: '90%'}, {duration: 1000})
}, 1000)
setTimeout(() => {
Velocity(document.querySelector('#b'), {left: '90%'}, {duration: 1000})
}, 2000)
setTimeout(() => {
Velocity(document.querySelector('#c'), {left: '90%'}, {duration: 1000})
}, 3000)
setTimeout(() => {
Velocity(document.querySelector('#d'), {left: '90%'}, {duration: 1000})
}, 4000)

Velocity.Utilities.dequeue(document.querySelectorAll('div')[0], 'a')
Velocity.Utilities.dequeue(document.querySelectorAll('div')[1], 'b')
Velocity.Utilities.dequeue(document.querySelectorAll('div')[2], 'c')
Velocity.Utilities.dequeue(document.querySelectorAll('div')[3], 'd')

動畫指令

fade 與 slide

Velocity 的 fade、slide 動畫指令與 jQuery 相似,可以製作 淡入/淡出、滑入/滑出的動畫效果。

  • jQuery
// 'fadeIn'、'fadeOut'、'slideUp'、'slideDown'
$('div').velocity('fadeOut', {duration: 2000})
  • JavaScript
Velocity(document.querySelectorAll('div'), 'fadeOut', {
duration: 2000
})

scroll

  1. scroll 指令是非常棒的效果,可以滾動瀏覽器內容到目標元素的位置。
  • jQuery
$('div').eq(2).velocity('scroll', {duration: 1500})
  • JavaScript
Velocity(document.querySelectorAll('div')[3], 'scroll', {duration: 2000})
  1. 滾動到具有 overflow 元素的內容位置

當一個元素的內容部分溢位(overflow)產生滾動條,可以使用 “scroll” 將內容滾動到指定的位置,container 選項對應為該元素(父容器)的選擇器。容器元素的 CSS 位置屬性必須設置為 relative,absolute 或 fixed,若沒有設定似乎會捲動比較快?

  • jQuery
$('#element4').velocity('scroll', {container: $('#box'), duration: 3000})
  • JavaScript
Velocity(document.querySelector('#element4'), 'scroll', {container: document.querySelector('#box'), duration: 3000})
  • 結構
<div id="box" style="height:100px;width:200px;overflow:auto">
<p id="element1">
1 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud.
</p>
<p id="element2">
2 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud
</p>
<p id="element3">
3 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud.
</p>
<p id="element4">
4 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud.
</p>
<p id="element5">
5 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud.
</p>
<p id="element6">
6 element. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud
</p>
</div>
  1. 設定水平或垂直捲軸滾動方向

在兩種情況下(無論滾動是相對於瀏覽器窗口還是相對於包含元素),可以設定水平或垂直捲軸滾動的方向。預設情況下,滾動發生在 Y 軸上。傳遞軸:’x’ 選項,而不是水平滾動。如果要設定 x 軸,必須將子元素橫向排列,並且產生水平捲軸。

Velocity(document.querySelector('#element4'), 'scroll', {axis: 'x', container: document.querySelector('#box'), duration: 3000})
  1. 設定滾動相對偏移量(以像素為單位)

除了設定滾動到指定元素的位置,還可以設定滾動至元素 offset 的偏移量。另外傳遞 mobileHA:false 可以避免在 iOS 上出現潛在的閃爍問題。

  • jQuery
$('#b').velocity('scroll', {offset: 250, duration: 3000})
  • JavaScript
Velocity(document.querySelector('#b'), 'scroll', {offset: 250, duration: 3000})

stop

要立即停止元素上所有當前的 Velocity 調用(包括通過 queue:false 調用的並行動畫),請將’stop’作為 Velocity 的第一個參數傳遞。元素的動畫隊列中的下一個 Velocity 調用立即開始。

$element.velocity('stop') // 停止正在執行的 $element 元素的動畫
$element.velocity('stop', 'myQueue') // 停止某自定義佇列

第二參數如果設定 true,停止動畫並且清除動畫隊列,在下方,最初的 {width:100} 調用將立即停止,隨後的 {height:200} 將被清除並完全跳過(它將永遠不會運行)。

/* 動畫佇列 */
$element.velocity({width: 100}, 1000).velocity({height: 200}, 1000)
/* Called immediately after. */
$element.velocity('stop', true)

finish

“finish” 指令會停止當前正在執行的動畫,並直接跳轉到動畫結束的狀態(無過渡)

reverse

“reverse” 指令使動畫反向執行,就像讓一部電影倒著播放。Reverse 預設會繼承之前動畫的配置選項(比如 duration,easing 等),但也可以重新設定。

$element.velocity({left: 200}, {duration: 500}).velocity('reverse', {duration: 2000})

特色動畫

transform

$element.velocity({
translateX: '200px',
rotateZ: '45deg'
})
  • 以下列舉了所有常用的 transform 相關可用屬性:
{
/* translate */
translateX: 20, // 等同於"20px"
translateY: "1.5em",
translateZ: "20px", // IE10+

/* scale */
scale: 0.5,
scaleX: 0.5,
scaleY: 0.5,

/* rotate */
rotate: 45, // 等同於"45deg"
rotateX: "45deg", // IE10+
rotateY: "45deg", // IE10+
rotateZ: "45deg",

/* skew */
skewX: "30deg",
skewY: "30deg",
}

colors

Velocity 顏色動畫支援的顏色屬性有:color, backgroundColor, borderColor, outlineColor。屬性值支援:rgb, hsla, 十六進位制顏色碼,但不支援顏色名稱,例如:”green”。

$element.velocity({
backgroundColor: '#ff0000',
/* 背景色 RGBA 中的 A 透明度到50% */
backgroundColorAlpha: 0.5,
/* 字型顏色 RGB 中的 Red 到 50% (0.5 * 255) */
colorRed: '50%',
/* 字型顏色 RGB 中的 Blue 值疊加50 */
colorBlue: '+=50',
/* 字型顏色 RGBA 中的 A 透明度到85% */
colorAlpha: 0.85
})

Hook

Hook 可以設定多個 CSS 屬性中的單獨一個值,比如 “boxShadow”, “clip”等,作用與 jQuery 的$.css()方法相似。

$.Velocity.hook($element, 'translateX', '500px') // 值必須寫上單位
$.Velocity.hook(elementNode, 'textShadowBlur', '10px') // 值必須寫上單位

還可以獲取單個 CSS 屬性的值

$.Velocity.hook($element, 'translateX') // 獲取元素的translateX值
$.Velocity.hook(elementNode, 'textShadowBlur')

promises

Velocity 可以使用 ES6 的 Promises 物件的語法方式

/* 使用 Velocity 的公有方法,$element 為 dom 選擇器 可以用 jQuery 的 或 原生js */
$.Velocity.animate($element, {opacity: 0.5})
/* 一旦動畫執行完成 執行下面.then()中的回撥函式(可以寫多個.then())*/
.then(function (elements) {
console.log('Resolved.')
})
/* 捕獲錯誤後的回撥函式 */
.catch(function (error) {
console.log('Rejected.')
})