/ Work

[jQuery note.] 在 hover 上微妙的變化

通常我們對於 .hover 這個事件的印象,就如同於 .mouseenter.mouseleave 這兩個事件的合體。這種互動式(Interaction Helpers)的事件在 jQuery 中還有一個,叫做 .toggle,在這裡就暫且不提。

一般來說,我們使用 .hover 的時候,就是希望能夠監聽使用者的滑鼠動作,然後在某種條件下觸發事件。那麼,最簡單的例子就是這樣

<!DOCTYPE html>
<html> 
<head> 
<meta http-equiv="content-Type" content="text/html; charset=utf-8" /> 
<title>hover test</title> 
<style type="text/css">
<!--
#hover_one {
    width: 100px;
    height: 100px;
    border: 1px solid #efefef;
    background-color: #333333;
    opacity: 1;
    color: #ffffff;
}
-->
</style>
</head>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
//<![CDDA[
$(document).ready(function() {
    $('#hover_one').hover(function() {
        $(this).animate({ 'opacity':0.5 });
    }, function() {
        $(this).animate({ 'opacity':1 });
    });
});
//]]>
</script>
<body>
<div id="container">
    <div id="hover_one">Mouse Enter/Leave Here.</div>
</div>
</body> 
</html>

我們把這個東西放到 Chrome 中實作,當你在區塊中將滑鼠移入(mouseenter)與移出(mouseleave)的時候,他會改變該區塊的透明度。也許你會問,這樣有甚麼問題?其實是有的,當你快速的在該區塊移入移出的時候,你就會發現問題在哪裡了。

發現了嗎?當你的滑鼠在快速移入移出的時候,.hover 會很誠實的把你移動所觸發的事件全部做完,這是好事,但是其中所使用的動態效果,在滑鼠結束移動之後還是繼續作用,這就不一定是好事了。

範例中的方格,就像是著猴(台語)一樣猛閃!

我們由 .hover 特性可以得知,他會很忠誠的,將所觸發的事件的總次數給做完,但是由於觸發事件中,包含了 animate 的動態效果(Fade 之類的效果亦同),這些動態效果都有所謂的執行時間差,在 .hover 快速且重複性的呼叫下,animate 也很誠實的,將每一個步驟全部做完之後,才會結束。

事實上,我們有時候不希望 animate 那麼老實做完所有的事情,所以,我們可以用 stop() 來干涉他!

/// 請直接修改上述例子,加入 stop() 干涉!
$('#hover_one').hover(function() {
  $(this).stop().animate({ 'opacity':0.5 });
}, function() {
  $(this).stop().animate({ 'opacity':1 });
});

差異很明顯就出現了,在滑鼠快速移入移出的時候,Animate 因為受到 stop() 的干涉,所以並不會做完上一個動作,為什麼說是上一個動作?我們把 .hoverfnInfnOut 拆成循序的清單開來看:

  1. 滑鼠移入
  • 呼叫 stop()
  • 停止物件本身所有 animate 效果
  • 呼叫 animate()
  • 執行物件本身 animate 效果
  • 滑鼠移出
  • 呼叫 stop()
  • 停止物件本身所有 animate 效果
  • 呼叫 animate()
  • 行物件本身 animate 效果

從 1. 滑鼠移入開始看,由於一開始物件並沒有任何動態效果,所以 stop() 其實等於沒有做事,然後,待等到 6. 滑鼠移出後,此時 7. 所呼叫的 stop() 就有效果了,8. 所停止的動態效果,其實是由 4. 的呼叫所產生,這也是為什麼我說他是干涉上一個動作的原因。

以任何的動態效果來說,使用 stop() 是可以有效的干涉其進行的步驟,對於 .hover 本身其實並沒有影響,以 .hover 的角度來看,他還是不斷的去執行 fnInfnOut 的動作。所以,倘若你要在 .hover 中呼叫其他的函式,最好還是使用旗標的方式來註記目前的執行狀態是 fnIn 還是 fnOut,避免重覆大量的呼叫而造成無法預期的結果。

stop() 還可以傳兩個參數,cleanQueuejumpToEnd,你可以自行試試看。

Hina Chen

Hina Chen

偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。

Read More