jQuery - 動畫

動畫設定

jQuery 的 animate 只支援任何「數字 + 單位」的屬性,且均為單個數值,例如 width、height、left,它們都可以是數字 + 單位(例如:100px),background-color 就不行,除非使用 jQuery.ColorjQuery UI來擴充功能,jQuery UI 還可以擴充 easing 動畫速率使用種類(jQuery 只提供 swing 與 linear)。

若沒有特別指定其他單位,jQuery 都會將預設視為 px。CSS 樣式名稱的寫法可採用「駝峰式命名」,若要採用原樣式連字號(-)寫法,會被視為不合法的識別字,必須加上引號,因此 magin-left 可以寫成maginLeft'magin-left',兩種都沒問題,寫作風格上還是建議使用「駝峰式命名」。

除了可以設定 CSS 樣式屬性,還可以對某些非樣式屬性,例如:scrollTop(捲軸最上方的偏移量)和scrollLeft(捲軸最左側的偏移量)。

注意,動畫不支援速記縮寫 CSS 屬性(例如:font、background、border),沒有插件下也無法動態調整顏色、字型種類或列舉屬性。

要指定相對值,可在數值前加上+=來增加該值,或是用-=來減少該值,中間不能有空格:

$('#box').on('click', function () {
$(this).animate({
marginLeft: '+=50', // 注意裡面不能有空格
opacity: '-=.1'
})
})

另外,還有其他三個字串屬性值hideshowtoggle 可用於動畫物件中:提供快速便捷可以隱藏、顯示或切換的功能。

$('#btn').on('click', function () {
$('#box').animate({
height: 'toggle',
borderLeft: 'toggle',
borderRight: 'toggle',
paddingLeft: 'toggle',
paddingRight: 'toggle'
})
})

使用 top、right、bottom、left 定位等位移屬性,必須確定 position 不能為 static,才會有作用。

// position 不能為 static
$('.box').animate({ left: '500px' }, 1000)

隱藏的元素仍然會被動畫影響。

// 潛行移動
$('.box').fadeTo(1000, 0).animate({ left: '500px' }, 1000).fadeTo(1000, 1)

jQuery 的動畫預設都會被放進佇列等待,因此動畫會一個接著一個依序進行。

// 動畫佇列
$('.box').fadeOut().show(300).slideUp().slideToggle()

動畫語法

animate 動畫語法分為兩種,第一種是書本或教學常看到的四參數語法,第二種是雙物件語法。

jQuery 內建動畫(fade、show、slide)全部可以用 animate() 來實現。

四參數語法

教學範例時常看到的語法,可以設定樣式物件、持續時間、動畫速率、完成後的回呼函式。

.animate( properties [, duration ] [, easing ] [, complete ] )

參數名稱 資料類型 說明
properties PlainObject json 物件格式,動畫要使用的 CSS 屬性
duration Number or String 動畫將運行多長時間,預設 400,’fast’ 為 200,’slow’ 為 600
easing String 預設字串’swing’,指示要用於過渡的緩動函數
complete Function 動畫完成後要調用的函式
$('.box').animate({ width: 300 }, 1000, 'linear', function () {
console.log('動畫完成')
})

雙物件語法

強烈推薦使用雙物件語法,兩參數分別使用了 json 物件格式,此語法可以設定動畫所有功能,就問你要不要用。

.animate( properties, options )

  • 樣式設定(properties):即是 CSS 樣式物件,與語法一相同。

  • 選項設定(Options):作為 animate 第二種語法的第二參數,它可以設定所有動畫的細節。

選項設定

選項物件設定屬性 說明
duration 預設 400,字串或數字,確定動畫將運行多長時間
easing 預設字串’swing’,指示要用於過渡的緩動函數,另一值為’linear’。
queue 預設:true,布林值或字符串,是否要將動畫放在佇列中,使用字串必須.dequeue(‘queuebame’)來啟動它
specialEasing 可指定不同屬性且具有不同速率
start 動畫開始時要調用的函式
step 動畫步進功能時要調用的函式
progress 動畫每個步驟之後要調用的函式
complete 動畫完成後要調用的函式
done 動畫完成(解析其 Promise 對象)時要調用的函式
fail 動畫失敗要調用的函式
always 動畫不管完成或失敗都會執行的函式

duration

動畫運行持續時間,以毫秒為單位,預設 400,也可以用字串’fast’等於 200 或’slow’等於 600 或任何定義於 jQuery.fx.speeds 中的名稱來指定。

easing

easing 函式(緩動函式),jQuery 介於 0 與 1 之間的值來呼叫 easing 函式,jQuery 會基於這個回傳值來計算對應的 CSS 屬性值。兩個值之間的變化可以是非線性的,這種變化使得動畫看起來會加速與減速。預設的 easing 函式為正弦曲線函數(swing):一開始進行緩慢,逐漸加速,之後再次慢下來直到最後值的動畫。另外還有linear的線性函式,也可以將自己的 easing 函式加入 jQuery.easing 物件中。

jQuery.easing['squareroot'] = Math.sqrt

想增加 easing 速率函式嗎?可以使用以下其中一種:

你可以在此網站參考各種速率的變化。

specialEasing

一個 json 物件,可指定不同屬性且具有不同速率,允許為想要變動的不同 CSS 屬性指定不同的 easing 函式,也就是為每個屬性可以定義自己的 easing 函式,以下有兩個方法:

// 隱藏圖像,動畫 Easing 預設為 swing 函數,藉由 specialEasing 將 width、height 更改為 linear 函數
$('#box').animate(
{
width: 'hide',
height: 'hide',
opacity: 'hide'
},
{
specialEasing: {
width: 'linear',
height: 'linear'
}
}
)

// 另外一種方式,在第一個物件引數傳入[目標值,easing函式]陣列。
$('#box').animate({
width: ['hide', 'linear'],
height: ['hide', 'linear'],
opacity: 'hide'
})

queue

是否要將動畫放在佇列中,預設為 true,布林值或字符串,從 jQuery 1.7 開始,queue 選項還可以接受一個字符串,在這種情況下,動畫將添加到該字符串表示的隊列中。使用自定義隊列名稱時,動畫不會自動開始,必須.dequeue(‘queuename’)來啟動它。

queue 動畫佇列,具有先進先出的概念,先設定的動畫會被擺在第一個位置,再設定的動畫會被 push 進來,做完的第一個動畫會 shift()出去,後面排隊的會遞補到第一個再做,若又有新的動畫會再被 push()進來。queue 若設為 false,不會被排入佇列,沒在佇列中的動畫會先執行。

<style>
.box {
width: 100px;
height: 100px;
background-color: #000;
position: absolute;
top: 0;
left: 0;
}
</style>
<div class="box"></div>
<script>
$('.box').on('click', clickHandler)
function clickHandler() {
$(this)
.animate(
{
top: 500,
left: 800
},
{
duration: 3000,
specialEasing: {
top: 'linear',
left: 'easeInOutBounce'
}
}
)
.animate(
{
top: 0,
left: 0
},
{
duration: 3000,
specialEasing: {
top: 'easeInOutBounce',
left: 'linear'
}
}
)
console.log($(this).queue())
}
</script>

step

每步動畫要執行的函式。啟用自定義動畫類型或改變正在執行的動畫,此功能是非常有用。它接受兩個參數(now 和 fx),this 是當前正在執行動畫的 DOM 元素集合。

  • now: 每一步動畫屬性的數值
  • fx:jQuery.fx 原型對象的一個引用,其中包含了多項屬性,比如 elem 表示前正在執行動畫的元素,start 和 end 分別為動畫屬性的第一個和最後一個的值,prop 為進行中的動畫屬性。
$('.box').animate(
{ left: 100, top: 100, width: 200, height: 200 },
{
duration: 1000,
step: function (now, fx) {
console.log(now)
console.log(fx)
}
}
)

progress

每一步動畫完成後調用的一個函數,無論動畫屬性有多少,每個動畫元素都只執行一次。

$('.box').animate(
{ left: 100, top: 100, width: 200, height: 200 },
{
duration: 1000,
progress: function (promise, progress, lessTime) {
console.log(promise) // promise 動畫元件
console.log(progress) // 動畫進度
console.log(lessTime) // 剩餘時間
}
}
)

start

動畫開始要執行的函式。

complete

動畫完成後要調用的函式。

done

在動畫完成時執行的函數。(它的 Promise 對象狀態已完成)

fail

動畫失敗完成時執行的函數。(它的 Promise 對象狀態未完成)

always

在動畫完成或未完成情況下停止時執行的函數。(它的 Promise 對象狀態已完成或未完成)

內建動畫

jQuery 定義了三組效果方法用以「隱藏」或「顯示」元素:它們的持續時間以毫秒為單位,預設都為 400,並提供字串’fast’和’slow’,分別為 200 和 600 毫秒。

show()、hide()

不帶引數呼叫時,show()與 hide()會即刻顯示或隱藏所選元素,hide()會把元素從版面配置上移除,將其 CSS 屬性 display:none。
以持續時間(或是選項物件)引數呼叫時,會呈現動態改變隱藏或顯示過程,會將元素的 width、height、opacity、margin、padding 慢慢降為 0,最後變成 display:none,show()則是設為 display:block。

$(selector).show()
$(selector).show(duration, completeFunction )
$(selector).show(duration, easing, completeFunction )
$(selector).show.hide(Options)

請注意,如果沒有 duration(持續時間)或指定的 duration(持續時間)為 0,.hide() 會立即觸發,並且將覆蓋動畫佇列。

toggle()

toggle()會切換狀態,若是隱藏就呼叫 show(),若是可見就呼叫 hide()。跟 show()與 hide()一樣,必須傳入持續時間或選項物件給 toggle(),可傳 true 給 toggle()等同於不帶引數呼叫 show(),傳 false 等同於不帶引數呼叫 hide()。

$(selector).toggle(boolean)
$(selector).toggle(duration, completeFunction)
$(selector).toggle(duration, easing, completeFunction )
$(selector).toggle(options)

fadeIn()、fadeOut()

淡入/淡出會動態的調整 CSS opacity 屬性來顯示或隱藏一個元素。值得注意的是fadeOut 若 opacity:0,最後元素會變成 display:none,隱藏起來不再引響頁面的佈局

.fadeIn( [duration ] [, complete ] )
.fadeIn( [duration ] [, easing ] [, complete ] )
.fadeIn( options )

.fadeOut( [duration ] [, complete ] )
.fadeOut( [duration ] [, easing ] [, complete ] )
.fadeOut( options )

fadeTo()

與其他效果方法稍微不同:對 fadeTo() 而言,第一引數 duration 是必須的,第二引數目標 opacity 也是必須的,而 complete 則是非必須的第三引數。它預期一個 opacity 目標引數,動態從元素目前的 opacity 調整至目標值,注意的是 fadeTo 如果為 0 時,並不會讓元素 display:none,它就是 opacity:0

.fadeTo( duration, opacity [, complete ] )
.fadeTo( duration, opacity [, easing ] [, complete ] )

faceToggle()

fadeToggle()方法執行匹配元素的不透明度動畫。當被可見元素調用時,元素不透明度一旦達到 0,display 樣式屬性設置為 none,所以元素不再影響頁面的佈局。

.fadeToggle( [duration ] [, easing ] [, complete ] )
.fadeToggle( options )

slideDown()、slideUp()

slideUp()會透過動態地將它們的 CSS height 屬性調整為 0 來隱藏 jQuery 物件中的元素,最後將元素 CSS display 設為 none。slideDown()則反過來讓一個隱藏的元素變為可見。

.slideDown( [duration ] [, complete ] )
.slideDown( [duration ] [, easing ] [, complete ] )
.slideDown( options )

.slideUp( [duration ] [, complete ] )
.slideUp( [duration ] [, easing ] [, complete ] )
.slideUp( options )

slideToggle()

slideToggle()則會使用向上滑動(slide Up)或向下滑動(slide Down)的切換一個項目的高度進行動畫效果,height 為 0 時,display:none。

.slideToggle( [duration ] [, complete ] )
.slideToggle( [duration ] [, easing ] [, complete ] )
.slideToggle( options )

注意,這三組方法都「非必須」接受持續時間、回呼函式、選項物件引數。而且 fadeOut()、hide()、slideUp(),最後都會將 css display 設定為 none。

停止或延緩動畫

停止動畫 stop()

接受兩個額外的 boolean 引數。

stop(clearQueue,jumpToEnd)
預設值 stop(false,false)

第一引數,停止第一個動畫後,是否清除之後等待的動畫佇列。預設為 false,停止第一個動畫,不會取消動畫佇列。
第二引數,是否跳到停止第一個動畫的最後狀態,預設為 false,不會跳至第一個停止動畫結束狀態。

以下為四種狀態範例:

<style>
.box {
width: 100px;
height: 100px;
background-color: #000;
position: absolute;
top: 0;
left: 0;
}
</style>
<div class="box"></div>
<script>
$('.box').on('click', clickHandler)
function clickHandler() {
// false,false
// 停止第一個動畫,false 不清除之後佇列(第二個),fasle 不跳至第一個動畫的最後狀態
// 最後效果為:left:100 之後再 top:200
$(this).animate({ left: 1000 }).animate({ left: 100 }).stop(false, false).animate({ top: 200 })

// true,false
// 停止第一個動畫,true 清除之後佇列(第二個),fasle 不跳至第一個動畫的最後狀態
// 最後效果為:直接移動 top:200
$(this).animate({ left: 1000 }).animate({ left: 100 }).stop(true, false).animate({ top: 200 })

// false,true
// 停止第一個動畫,false 不清除之後佇列(第二個),true 跳至第一個動畫的最後狀態
// 最後效果為:從第一個動畫最後狀態 left:1000 開始,接著移動 left:100,再移動 top:200
$(this).animate({ left: 1000 }).animate({ left: 100 }).stop(false, true).animate({ top: 200 })

// true,true
// 停止第一個動畫,true 清除之後佇列(第二個),true 跳至第一個動畫的最後狀態
// 最後效果為:從第一個動畫最後狀態 left:1000 開始,接著移動 top:200
$(this).animate({ left: 1000 }).animate({ left: 100 }).stop(true, true).animate({ top: 200 })
}
</script>

stop 應用 + 兩種事件寫法

// 由於預設 stop(false,false),滑鼠移入時會立刻停在當下動畫狀態,並在滑鼠移開時繼續變深
// 若都沒有 stop(),則滑鼠移入會先變淡至0.1,再變回 1
// 第一種用 on 並傳入一個選項物件
$('.box').on({
mouseover: function () {
$(this).stop().fadeTo(3000, 0.1)
},
mouseout: function () {
$(this).stop().fadeTo(3000, 1)
}
})

// 第二種用 hover(),使用兩個參數
// $(選擇器).hover(func1,func2)
$('img').hover(
function () {
$(this).stop().fadeTo(3000, 0.1)
},
function () {
$(this).stop().fadeTo(3000, 1)
}
)

延遲動畫 delay()

加入一段時間延遲(timed delay)到動畫佇列:
第一個引數以毫秒為單位傳入一段持續時間數字(或持續時間字串),第二引數為非必須的下一個佇列名稱(queue name),通常不需要第二個引數

.delay( duration [, queueName ] )

// 2秒淡出到0.1,然後等3秒,再向上滑動
$('.box').fadeTo(2000, 0.1).delay(3000).hide()

使用 mouseover 與 mouseout 事件來變動圖像的不透明(opacity),在動畫前加入一段短暫的時間延遲來改善,滑鼠快速地移過一個圖像而不停下來,不會有令人分心的動畫出現。

$('img').bind({
mouseover: function () {
$(this).stop(true).delay(100).fadeTo(300, 0.1)
},
mouseout: function () {
$(this).stop(true).fadeTo(300, 1)
}
})