怎么用javascript進行拖拽2
更新時間:2006年07月20日 00:00:00 作者:
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
你會注意到這個代碼幾乎是前面的全集,將前面的合在一起就實現了拖拽效果了.
當我們點擊一個item時,我們就獲取了很多變量,如鼠標位置,鼠標位置自然就包含了那個item的坐標信息了.如果我們點擊了一個20*20px圖像的正中間,那么鼠標的相對坐標為{x:10,y:10}.當我們點擊這個圖像的左上角那么鼠標的相對坐標為{x:0,y:0}.當我們點擊時,我們用這個方法取得一些鼠標與圖片校對的信息.如果我們不能加載頁面item,那么信息將是document信息,會忽略了點擊的item信息.
mouseOffset函數使用了另一個函數getPosition.getPosition的作用是返回item相對頁面左上角的坐標,如果我們嘗試獲取item.offsetLeft或者item.style.left,那么我們將取得item相對與父級的位置,不是整個document.所有的腳本我們都是相對整個document,這樣會更好一些.
為了完成getPosition任務,必須循環(huán)取得item的父級,我們將加載內容到item的左/上的位置.我們需要管理想要的top與left列表.
自從定義了mousemove這個函數,mouseMove就會一直運行.第一我們確定item的style.position為absolute,第二我們移動item到前面定義好的位置.當mouse點擊被釋放,dragObject被設置為null,mouseMove將不在做任何事.
Dropping an Item
前面的例子目的很簡單,就是拖拽item到我們希望到的地方.我們經常還有其他目的如刪除item,比如我們可以將item拖到垃圾桶里,或者其他頁面定義的位置.
很不幸,我們有一個很大的難題,當我們拖拽,item會在鼠標之下,比如mouseove,mousedown,mouseup或者其他mouse action.如果我們拖拽一個item到垃圾桶上,鼠標信息還在item上,不在垃圾桶上.
怎么解決這個問題呢?有幾個方法可以來解決.第一,這是以前比較推薦的,我們在移動鼠標時item會跟隨鼠標,并占用了mouseover/mousemove等鼠標事件,我們不這樣做,只是讓item跟隨著鼠標,并不占用mouseover等鼠標事件,這樣會解決問題,但是這樣并不好看,我們還是希望item能直接跟在mouse下.
另一個選擇是不做item的拖拽.你可以改變鼠標指針來顯示需要拖拽的item,然后放在鼠標釋放的位置.這個解決方案,也是因為美學原因不予接受.
最后的解決方案是,我們并不去除拖拽效果.這種方法比前兩種繁雜許多,我們需要定義我們需要釋放目標的列表,當鼠標釋放時,手工去檢查釋放的位置是否是在目標列表位置上,如果在,說明是釋放在目標位置上了.
復制代碼 代碼如下:
/*
All code from the previous example is needed with the exception
of the mouseUp function which is replaced below
*/
var dropTargets = [];
function addDropTarget(dropTarget){
dropTargets.push(dropTarget);
}
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
for(var i=0; i<dropTargets.length; i++){
var curTarget = dropTargets[i];
var targPos = getPosition(curTarget);
var targWidth = parseInt(curTarget.offsetWidth);
var targHeight = parseInt(curTarget.offsetHeight);
if(
(mousePos.x > targPos.x) &&
(mousePos.x < (targPos.x + targWidth)) &&
(mousePos.y > targPos.y) &&
(mousePos.y < (targPos.y + targHeight))){
// dragObject was dropped onto curTarget!
}
}
dragObject = null;
}
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
鼠標釋放時會去取是否有drop屬性,如果存在,同時鼠標指針還在drop的范圍內,執(zhí)行drop操作.我們檢查鼠標指針位置是否在目標范圍是用(mousePos.x>targetPos.x),而且還要符合條件(mousePos.x<(targPos.x + targWidth)).如果所有的條件符合,說明指針確實在范圍內,可以執(zhí)行drop指令了.
Pulling It All Together
最后我們擁有了所有的drag/drop的腳本片斷!下一個事情是我們將創(chuàng)建一個DOM處理.如果你不是很熟悉,請先閱讀我的JavaScript Primer on DOM Manipulation.
下面的代碼將創(chuàng)建container(容器),而且使任何一個需要drag/drop的item變成一個容器的item.代碼在這個文章第二個demo的后面,它可以用戶記錄一個list(列表),定為一個導航窗口在左邊或者右邊,或者更多的函數你可以想到的.
下一步我們將通過"假代碼"讓reader看到真代碼,下面為推薦:
1、當document第一次載入時,創(chuàng)建dragHelper DIV.dragHelper將給移動的item加陰影.真實的item沒有被dragged,只是用了insertBefor和appendChild來移動了,我們隱藏了dragHelper
2、有了mouseDown與mouseUp函數.所有的操作會對應到當到iMouseDown的狀態(tài)中,只有當mouse左鍵為按下時iMouseDown才為真,否則為假.
3、我們創(chuàng)建了全局變量DragDrops與全局函數CreateDragContainer.DragDrops包含了一系列相對彼此的容器.任何參數(containers)將通過CreatedcragContainer進行重組與序列化,這樣可以自由的移動.CreateDragContainer函數也將item進行綁定與設置屬性.
4、現在我們的代碼知道每個item的加入,當我們移動處mouseMove,mouseMove函數首先會設置變量target,鼠標移動在上面的item,如果這個item在容器中(checked with getAttribute):
運行一小段代碼來改變目標的樣式.創(chuàng)造rollover效果
檢查鼠標是否沒有放開,如果沒有
設置curTarget代表當前item
記錄item的當前位置,如果需要的話,我們可以將它返回
克隆當前的item到dragHelper中,我們可以移動帶陰影效果的item.
item拷貝到dragHelper后,原有的item還在鼠標指針下,我們必須刪除掉dragObj,這樣腳本起作用,dragObj被包含在一個容器中.
抓取容器中所有的item當前坐標,高度/寬度,這樣只需要記錄一次,當item被drag時,每隨mouse移動,每移鐘就會記錄成千上萬次.
如果沒有,不需要做任何事,因為這不是一個需要移動的item
5、檢查curTarget,它應該包含一個被移動的item,如果存在,進行下面操作:
開始移動帶有陰影的item,這個item就是前文所創(chuàng)建的
檢查每個當前容器中的container,是否鼠標已經移動到這些范圍內了
我們檢查看一下正在拖動的item是屬于哪個container
放置item在一個container的某一個item之前,或者整個container之后
確認item是可見的
如果鼠標不在container中,確認item是不可見了.
6、剩下的事就是捕捉mouseUp的事件了

