本篇主要討論了IE和FireFox在層的拖動(dòng)實(shí)現(xiàn)過程中的一些不同和一些常見問題,其他元件的拖動(dòng)也是同樣的道理,這里以使用較多的層元件為例進(jìn)行解釋。
層的拖動(dòng)涉及了以下三個(gè)鼠標(biāo)事件:
onmousedown:點(diǎn)下鼠標(biāo)
onmousemove:移動(dòng)鼠標(biāo)
onmouseup:松開鼠標(biāo)
拖動(dòng)基本過程:
點(diǎn)下鼠標(biāo)時(shí),開始拖動(dòng),記下鼠標(biāo)指針位置與被拖動(dòng)元件的相對(duì)位置x;
鼠標(biāo)移動(dòng)時(shí),根據(jù)鼠標(biāo)指針的位置和相對(duì)元件位置x計(jì)算出元件的位置,并設(shè)置元件位置;
松開鼠標(biāo)時(shí),要銷毀鼠標(biāo)移動(dòng)的事件處理程序,停止拖動(dòng)。
下面來看一個(gè)層拖動(dòng)的具體例子:
代碼注釋:
1. 該實(shí)例使用drag()函數(shù)對(duì)某個(gè)元件添加事件處理程序以實(shí)現(xiàn)元件的拖動(dòng),傳入的參數(shù)o為要被拖動(dòng)的元件對(duì)象。
2. 必須將要拖動(dòng)的元件的位置設(shè)置為絕對(duì)定位(absolute),并設(shè)置左邊距和頂邊距。
3. layerX和layerY是Netscape的事件屬性,表示事件相對(duì)于包容圖層的X坐標(biāo)和Y坐標(biāo),在IE中它們則是offsetX和offsetY。
4. setCapture()和captureEvents()分別是IE和Netscape進(jìn)行設(shè)置事件捕獲源的函數(shù),在設(shè)置onmousemove和onmouseup事件處理程序前必須使用,IE的setCapture可以針對(duì)某個(gè)特定的元件設(shè)置事件捕獲,而Netscape中只能對(duì)整個(gè)文檔設(shè)置,這將會(huì)導(dǎo)致一些問題。對(duì)應(yīng)的停止捕捉事件函數(shù)為releaseCapture()和captureEvents()。
5. clientX、clientY以及pageX、pageY分別是IE和Netscape中事件發(fā)生位置相對(duì)于瀏覽器頁(yè)面的X坐標(biāo)和Y坐標(biāo)。
有時(shí)要對(duì)拖動(dòng)的范圍做一個(gè)限定,比如窗口的滑動(dòng)塊,這時(shí),只要稍稍修改onmousemove事件處理程序即可,在對(duì)元件定位前判斷其位置。
修改后代碼如下:
增加的一個(gè)傳入?yún)?shù)r指定了元件的移動(dòng)范圍,它是一個(gè)數(shù)組,包含的四個(gè)元素分別代表元件的左、右、上、下范圍。
接下來看一個(gè)在FireFox下會(huì)出現(xiàn)的問題,代碼如下:
要拖動(dòng)的層中包含的是一張圖片而不再是文字,這樣在IE中仍可以正常拖動(dòng),而在FireFox中會(huì)發(fā)生異常,點(diǎn)下鼠標(biāo)、拉動(dòng)、并松開后,層并沒有停止拖動(dòng),而是跟隨著鼠標(biāo)。
仔細(xì)地分析了一下原因,就是上面說過的Netscape的captureEvent()不能捕獲某個(gè)特定元件的事件,當(dāng)點(diǎn)下鼠標(biāo)并拉動(dòng)時(shí)時(shí),F(xiàn)ireFox會(huì)認(rèn)為要拖動(dòng)的對(duì)象是層里的圖片,該操作無效。
要解決這個(gè)問題,只要把圖片上的鼠標(biāo)點(diǎn)下事件設(shè)置為無效,在drag函數(shù)內(nèi)加上 o.firstChild.onmousedown=function(){return false;}; 即可。
最終代碼如下: