2011-09-16 68 views
38

我需要知道鼠標光標何時離開div。所以我連接mouseout事件。但是,如果我很快將鼠標移出div,則mouseout事件不會觸發。沒錯:鼠標光標坐在div內部,現在是外部div,但尚未調用mouseout回調。 (它可以很好地工作,如果我不移動鼠標的速度非常快)。爲什麼我不能可靠地捕捉鼠標事件?

順便說一句,這是最新Google Chrome - 這不僅僅是一個「舊瀏覽器」問題。

一種解決方法:

關於這個問題的問題一直posed before。顯然這只是一個生活中的事實,我發現的唯一解決方法是手動監視mousemove事件,每次檢查光標的x/y座標並查看它們是否屬於div的邊界框,因此您有如果光標不在其中,則有更多機會「注意」。

與讓瀏覽器在本地執行所有操作相比,對每個像素移動執行計算都會帶來一定的性能下降。編碼也很繁瑣。

到我的問題...

爲什麼不能在瀏覽器無法可靠地捕獲mouseout事件?如果我可以可靠地分辨鼠標何時使用上述解決方法離開div,爲什麼瀏覽器不能執行此操作?

我明白(從上面鏈接的答案)JavaScript不會嘗試插入「幀」。假設您在document上放置了一個mousemove處理程序,並在完美的水平線上快速移動鼠標200個像素到右邊,那麼您可能需要而不是獲取200 mousemove個事件。少數人會錯過。我沒有這個問題。

但是,如果在鼠標穿越div的邊界時錯過某些像素移動,爲什麼會彈出mouseout事件?當瀏覽器終於​​開始重新註冊鼠標的位置(在突然快速移動之後),即使鼠標現在在框外英里,問題是它以前是而不是。那麼爲什麼它不然後開始鼠標事件呢?

我只是不明白爲什麼這將是瀏覽器供應商解決的難題。 (但我相信可能有一個很好的理由,我太愚蠢的想法。)

我發佈這個問題主要出於好奇,但我希望答案可能會給一些洞察力,可以幫助我更有效地解決問題。此外,任何替代解決方法(比上面提到的更快)將受到歡迎。

+1

這是絕對沒有幫助你(因此評論,而不是答案),但這種行爲最肯定聽起來像一個錯誤。這也可能是顯而易見的,但是爲了解決你的問題「爲什麼會出現鼠標事件應該被跳過?」,答案是他*它不*,因爲它是非故意的行爲。 – jmar777

+0

有趣。這實際上對我很有幫助 - 如果你是對的,那是一個錯誤。對我來說似乎很奇怪,雖然這種錯誤會在Chrome 15中存在!我將製作一個測試頁面,並在其他瀏覽器中嘗試,看看它有多廣泛。我可能會向crbug.com提交一個錯誤報告,看看他們做了些什麼。謝謝。 – callum

+0

僅供參考:Chrome 15尚未進入穩定渠道 – Candide

回答

6

我知道你不想要一個解決方法,但是你不需要檢查鼠標的x/y來知道你是否在一個元素中。您可以簡單地檢查mousemove事件觸發的元素。如果您將鼠標移動到文檔上,該事件將從其子項中觸發,並且您可以將該元素與元素進行比較,以瞭解它是否是其後代之一。

或者你可以上去parentNode樹並停止,如果你找到你的元素。然後你知道你在這個元素裏面,仍然在裏面,否則你到達文檔,你就出來了。

有些瀏覽器實現了mouseenter/mouseleave事件,我注意到它比mouseout更精確。 Prototype和jQuery爲不實現這些新事件的瀏覽器提供了一種解決方法。 Mouseleave不會從元素的子元素中觸發,而mouseout則會觸發元素的子元素。

4

您描述很快移動鼠標。當你停下來時,指針是否仍在頁面內?也就是說,你的鼠標指針是否仍然懸停在可見網頁的某個部分?

如果它已經在外面了,那麼瀏覽器應該做什麼並不一定清楚。 mouseout事件應具有一個relatedTarget屬性,該屬性指向鼠標指針已進入的內容。如果鼠標指針已經在頁面區域之外,則不會有相關的目標指向。換句話說,當鼠標離開頁面區域時,瀏覽器停止跟蹤它並停止報告其位置。如果從瀏覽器的角度來看,移動鼠標足夠快,鼠標就會消失。直到您將鼠標移回瀏覽器知道其位置的可瀏覽頁面的邊界框中,然後觸發所有適當的基於移動的操作(如鼠標移出)。

0
  1. 爲什麼不能在瀏覽器無法可靠地捕獲mouseout事件?如果我可以可靠地告訴鼠標何時使用上述解決方法離開了div,爲什麼瀏覽器不能執行此操作?

    我想你回答這一個自己,當你說:

    比起讓瀏覽器做這一切本身,在每一個像素進行移動計算是一個有點性能損失。

    瀏覽器不在幀之間進行插值,因此,如您所述,它會要求更多的資源和內存,這可能是它不是「固定」的原因。

  2. 如果在鼠標穿過div的邊界時錯過某些像素移動,爲什麼會出現mouseout事件也會被跳過?當瀏覽器終於​​開始再次註冊鼠標的位置時(在突然快速移動之後),即使鼠標現在在盒子外面數英里,重點在於它曾經是在盒子中,不再是。那麼爲什麼它不然後開始鼠標事件呢?

    我不確定,但我不認爲這是「它在,現在它已經不在」的條件。相反,它是否跨越該邊界(如果MouseX - ElemOffsetX= 1)。我同意,這並沒有多大意義,但可能是因爲如果將值設置爲> 1,它會多次觸發事件。否則,它將不得不跟蹤事件,這不屬於JS本質,看它如何將事件添加到堆棧中。


什麼,你可以嘗試使用jQuery's mouseleave event。這做了兩兩件事,其中延遲在觸發事件:

  1. 它遍歷DOM樹,看它是否真正離開元素
  2. 我認爲它實現了一個超時調用,它要解決的插值問題你注意到了。
0

我發現你的問題和缺乏其他明確的答案有用,因爲它告訴我,我必須創建一個解決方法。我使用了你的問題和其他貢獻者提出的想法。我有同樣的問題,當我使用jquery mouseleave elem.bind('mouseleave',data,mouseLeavesZon​​e);當我使用jquery mouseleave elem.bind('mouseleave',data,mouseLeavesZon​​e);

問題是間歇性的,可能與客戶端上的繁忙CPU有關。比如說,當鼠標移出div時,CPU在其他地方很忙。那麼這可能是錯誤的原因似乎是合乎邏輯的。我同意;這應該由瀏覽器供應商解決。

http://jsfiddle.net/bgil2012/gWP5x/1/

(題外話:我的jQuery代碼需要使用舊的jQuery方法,因爲它必須在Drupal 7這是運行的jQuery 1.4上運行,在這個時候,不實施該來了補丁)。

1

我遇到了這個問題幾次,我開始接受這個問題作爲生活中的事實。但取決於您的需求,您可以像我一樣使用CSS。例如,如果我只想顯示/隱藏基於另一個元素的元素,那麼CSS就是要走的路。這裏是工作的,可靠的例子:

.large { 
    width: 175px; height: 175px; 
    position: absolute; 
    border-radius: 100%; 

    /*hide the glass by default*/ 
    top: -9999px; 
    left: -9999px; 
    opacity: 0; 
    transition: opacity .2s ease-in-out; 
    z-index: 100; 
    pointer-events: none; 
} 

.small:hover + .large { 
    opacity: 1; 
} 

http://codepen.io/tanduong/pen/aBMxyd