狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

用Javascript實(shí)現(xiàn)網(wǎng)頁(yè)表單鼠標(biāo)拖拽

admin
2010年11月28日 9:25 本文熱度 3508
  怎么用javascript進(jìn)行拖拽

  Javascript的特點(diǎn)是dom的處理與網(wǎng)頁(yè)效果,大多數(shù)情況我們只用到了這個(gè)語(yǔ)言的最簡(jiǎn)單的功能,比如制作圖片輪播/網(wǎng)頁(yè)的tab等等,這篇文章將向你展示如何在自己的網(wǎng)頁(yè)上制作拖拽.

  有很多理由讓你的網(wǎng)站加入拖拽功能,最簡(jiǎn)單的一個(gè)是數(shù)據(jù)重組.例如:你有一個(gè)序列的內(nèi)容讓用戶(hù)排序,用戶(hù)需要給每個(gè)條目進(jìn)行輸入或者用select選擇,替代前面這個(gè)方法的就是拖拽.或許你的網(wǎng)站也需要一個(gè)用戶(hù)可以拖動(dòng)的導(dǎo)航窗口!那么這些效果都是很簡(jiǎn)單:因?yàn)槟憧梢院苋菀椎膶?shí)現(xiàn)!

  網(wǎng)頁(yè)上實(shí)現(xiàn)拖拽其實(shí)也不是很復(fù)雜.第一你需要知道鼠標(biāo)坐標(biāo),第二你需要知道用戶(hù)鼠標(biāo)點(diǎn)擊一個(gè)網(wǎng)頁(yè)元素并實(shí)現(xiàn)拖拽,最后我們要實(shí)現(xiàn)移動(dòng)這個(gè)元素。

獲取鼠標(biāo)移動(dòng)信息

  第一我們需要獲取鼠標(biāo)的坐標(biāo).我們加一個(gè)用戶(hù)函數(shù)到document.onmousemove就可以了:



document.onmousemove = mouseMove;

function mouseMove(ev){
ev           = ev || window.event;
var mousePos = mouseCoords(ev);
}

function mouseCoords(ev){
if(ev.pageX || ev.pageY){
  return {x:ev.pageX, y:ev.pageY};
}
return {
  x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
  y:ev.clientY + document.body.scrollTop  - document.body.clientTop
};
}

  你首先要聲明一個(gè)evnet對(duì)象.不論何時(shí)你移動(dòng)鼠標(biāo)/點(diǎn)擊/按鍵等等,會(huì)對(duì)應(yīng)一個(gè)event的事件.在Internet Explorer里event是全局變量,會(huì)被存儲(chǔ)在window.event里. 在firefox中,或者其他瀏覽器,event事件會(huì)被相應(yīng)的自定義函數(shù)獲?。?dāng)我們將mouseMove函數(shù)賦值于document.onmousemove,mouseMove會(huì)獲取鼠標(biāo)移動(dòng)事件.

  (ev = ev || window.event) 這樣讓ev在所有瀏覽器下獲取了event事件,在Firefox下"||window.event"將不起作用,因?yàn)閑v已經(jīng)有了賦值.在MSIE下ev是空的,所以ev將設(shè)置為window.event.

  因?yàn)槲覀冊(cè)谶@篇文章中需要多次獲取鼠標(biāo)坐標(biāo),所以我們?cè)O(shè)計(jì)了mouseCoords這個(gè)函數(shù),它只包含了一個(gè)參數(shù),就是the event.

  我們需要運(yùn)行在MSIE與Firefox為首的其他瀏覽器下.Firefox以event.pageX和event.pageY來(lái)代表鼠標(biāo)相應(yīng)于文檔左上角的位置.如果你有一個(gè)500*500的窗口,而且你的鼠標(biāo)在正中間,那么paegX和pageY將是250,當(dāng)你將頁(yè)面往下滾動(dòng)500px,那么pageY將是750.此時(shí)pageX不變,還是250.

  MSIE和這個(gè)相反,MSIE將event.clientX與event.clientY來(lái)代表鼠標(biāo)與ie窗口的位置,并不是文檔.當(dāng)我們有一個(gè)500*500的窗口,鼠標(biāo)在正中間,那么clientX與clientY也是250,如果你垂直滾動(dòng)窗口到任何位置,clientY仍然是250,因?yàn)橄鄬?duì)ie窗口并沒(méi)有變化.想得到正確的結(jié)果,我們必須加入scrollLeft與scrollTop這兩個(gè)相對(duì)于文檔鼠標(biāo)位置的屬性.最后,由于MSIE并沒(méi)有0,0的文檔起始位置,因?yàn)橥ǔ?huì)設(shè)置2px的邊框在周?chē)吙虻膶挾劝赿ocument.body.clientLeft與clientTop這兩個(gè)屬性中,我們?cè)偌尤脒@些到鼠標(biāo)的位置中.

  很幸運(yùn),這樣mouseCoords函數(shù)就完成了,我們不再為坐標(biāo)的事操心了.


捕捉鼠標(biāo)點(diǎn)擊

  下次我們將知道鼠標(biāo)何時(shí)點(diǎn)擊與何時(shí)放開(kāi).如果我們跳過(guò)這一步,我們?cè)谧鐾献r(shí)將永遠(yuǎn)不知道鼠標(biāo)移動(dòng)上面時(shí)的動(dòng)作,這將是惱人的與違反直覺(jué)的.

  這里有兩個(gè)函數(shù)幫助我們:onmousedown與onmouseup.我們預(yù)先設(shè)置函數(shù)來(lái)接收document.onmousemove,這樣看起來(lái)很象我們會(huì)獲取document.onmousedown與document.onmouseup.但是當(dāng)我們獲取document.onmousedown時(shí),我們同時(shí)獲取了任何對(duì)象的點(diǎn)擊屬性如:text,images,tables等等.我們只想獲取那些需要拖拽的屬性,所以我們?cè)O(shè)置函數(shù)來(lái)獲取我們需要移動(dòng)的對(duì)象.

移動(dòng)一個(gè)元素

  我們知道了怎么捕捉鼠標(biāo)移動(dòng)與點(diǎn)擊.剩下的就是移動(dòng)元素了.首先,要確定一個(gè)明確的頁(yè)面位置,css樣式表要用'absolute'.設(shè)置元素絕對(duì)位置意味著我們可以用樣式表的.top和.left來(lái)定位,可以用相對(duì)位置來(lái)定位了.我們將鼠標(biāo)的移動(dòng)全部相對(duì)頁(yè)面top-left,基于這點(diǎn),我們可以進(jìn)行下一步了.

  當(dāng)我們定義item.style.position='absolute',所有的操作都是改變left坐標(biāo)與top坐標(biāo),然后它移動(dòng)了。


document.onmousemove = mouseMove;
document.onmouseup   = mouseUp;

var dragObject  = null;
var mouseOffset = null;

function getMouseOffset(target, ev){
ev = ev || window.event;

var docPos    = getPosition(target);
var mousePos  = mouseCoords(ev);
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}

function getPosition(e){
var left = 0;
var top  = 0;

while (e.offsetParent){
  left += e.offsetLeft;
  top  += e.offsetTop;
  e     = e.offsetParent;
}

left += e.offsetLeft;
top  += e.offsetTop;

return {x:left, y:top};
}

function mouseMove(ev){
ev           = ev || window.event;
var mousePos = mouseCoords(ev);

if(dragObject){
  dragObject.style.position = 'absolute';
  dragObject.style.top      = mousePos.y - mouseOffset.y;
  dragObject.style.left     = mousePos.x - mouseOffset.x;

  return false;
}
}
function mouseUp(){
dragObject = null;
}

function makeDraggable(item){
if(!item) return;
item.onmousedown = function(ev){
  dragObject  = this;
  mouseOffset = getMouseOffset(this, ev);
  return false;
}
}


  你會(huì)注意到這個(gè)代碼幾乎是前面的全集,將前面的合在一起就實(shí)現(xiàn)了拖拽效果了.

  當(dāng)我們點(diǎn)擊一個(gè)item時(shí),我們就獲取了很多變量,如鼠標(biāo)位置,鼠標(biāo)位置自然就包含了那個(gè)item的坐標(biāo)信息了.如果我們點(diǎn)擊了一個(gè)20*20px圖像的正中間,那么鼠標(biāo)的相對(duì)坐標(biāo)為{x:10,y:10}.當(dāng)我們點(diǎn)擊這個(gè)圖像的左上角那么鼠標(biāo)的相對(duì)坐標(biāo)為{x:0,y:0}.當(dāng)我們點(diǎn)擊時(shí),我們用這個(gè)方法取得一些鼠標(biāo)與圖片校對(duì)的信息.如果我們不能加載頁(yè)面item,那么信息將是document信息,會(huì)忽略了點(diǎn)擊的item信息.

  mouseOffset函數(shù)使用了另一個(gè)函數(shù)getPosition.getPosition的作用是返回item相對(duì)頁(yè)面左上角的坐標(biāo),如果我們嘗試獲取item.offsetLeft或者item.style.left,那么我們將取得item相對(duì)與父級(jí)的位置,不是整個(gè)document.所有的腳本我們都是相對(duì)整個(gè)document,這樣會(huì)更好一些.

  為了完成getPosition任務(wù),必須循環(huán)取得item的父級(jí),我們將加載內(nèi)容到item的左/上的位置.我們需要管理想要的top與left列表.

  自從定義了mousemove這個(gè)函數(shù),mouseMove就會(huì)一直運(yùn)行.第一我們確定item的style.position為absolute,第二我們移動(dòng)item到前面定義好的位置.當(dāng)mouse點(diǎn)擊被釋放,dragObject被設(shè)置為null,mouseMove將不在做任何事.

Dropping an Item

  前面的例子目的很簡(jiǎn)單,就是拖拽item到我們希望到的地方.我們經(jīng)常還有其他目的如刪除item,比如我們可以將item拖到垃圾桶里,或者其他頁(yè)面定義的位置.

  很不幸,我們有一個(gè)很大的難題,當(dāng)我們拖拽,item會(huì)在鼠標(biāo)之下,比如mouseove,mousedown,mouseup或者其他mouse action.如果我們拖拽一個(gè)item到垃圾桶上,鼠標(biāo)信息還在item上,不在垃圾桶上.

  怎么解決這個(gè)問(wèn)題呢?有幾個(gè)方法可以來(lái)解決.第一,這是以前比較推薦的,我們?cè)谝苿?dòng)鼠標(biāo)時(shí)item會(huì)跟隨鼠標(biāo),并占用了mouseover/mousemove等鼠標(biāo)事件,我們不這樣做,只是讓item跟隨著鼠標(biāo),并不占用mouseover等鼠標(biāo)事件,這樣會(huì)解決問(wèn)題,但是這樣并不好看,我們還是希望item能直接跟在mouse下.

  另一個(gè)選擇是不做item的拖拽.你可以改變鼠標(biāo)指針來(lái)顯示需要拖拽的item,然后放在鼠標(biāo)釋放的位置.這個(gè)解決方案,也是因?yàn)槊缹W(xué)原因不予接受.

  最后的解決方案是,我們并不去除拖拽效果.這種方法比前兩種繁雜許多,我們需要定義我們需要釋放目標(biāo)的列表,當(dāng)鼠標(biāo)釋放時(shí),手工去檢查釋放的位置是否是在目標(biāo)列表位置上,如果在,說(shuō)明是釋放在目標(biāo)位置上了.


/*
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;
}

  鼠標(biāo)釋放時(shí)會(huì)去取是否有drop屬性,如果存在,同時(shí)鼠標(biāo)指針還在drop的范圍內(nèi),執(zhí)行drop操作.我們檢查鼠標(biāo)指針位置是否在目標(biāo)范圍是用(mousePos.x>targetPos.x),而且還要符合條件(mousePos.x<(targPos.x + targWidth)).如果所有的條件符合,說(shuō)明指針確實(shí)在范圍內(nèi),可以執(zhí)行drop指令了.


Pulling It All Together

  最后我們擁有了所有的drag/drop的腳本片斷!下一個(gè)事情是我們將創(chuàng)建一個(gè)DOM處理.如果你不是很熟悉,請(qǐng)先閱讀我的JavaScript Primer on DOM Manipulation.

  下面的代碼將創(chuàng)建container(容器),而且使任何一個(gè)需要drag/drop的item變成一個(gè)容器的item.代碼在這個(gè)文章第二個(gè)demo的后面,它可以用戶(hù)記錄一個(gè)list(列表),定為一個(gè)導(dǎo)航窗口在左邊或者右邊,或者更多的函數(shù)你可以想到的.

  下一步我們將通過(guò)"假代碼"讓reader看到真代碼,下面為推薦:

  1、當(dāng)document第一次載入時(shí),創(chuàng)建dragHelper DIV.dragHelper將給移動(dòng)的item加陰影.真實(shí)的item沒(méi)有被dragged,只是用了insertBefor和appendChild來(lái)移動(dòng)了,我們隱藏了dragHelper

  2、有了mouseDown與mouseUp函數(shù).所有的操作會(huì)對(duì)應(yīng)到當(dāng)?shù)絠MouseDown的狀態(tài)中,只有當(dāng)mouse左鍵為按下時(shí)iMouseDown才為真,否則為假.

  3、我們創(chuàng)建了全局變量DragDrops與全局函數(shù)CreateDragContainer.DragDrops包含了一系列相對(duì)彼此的容器.任何參數(shù)(containers)將通過(guò)CreatedcragContainer進(jìn)行重組與序列化,這樣可以自由的移動(dòng).CreateDragContainer函數(shù)也將item進(jìn)行綁定與設(shè)置屬性.

  4、現(xiàn)在我們的代碼知道每個(gè)item的加入,當(dāng)我們移動(dòng)處mouseMove,mouseMove函數(shù)首先會(huì)設(shè)置變量target,鼠標(biāo)移動(dòng)在上面的item,如果這個(gè)item在容器中(checked with getAttribute):

  運(yùn)行一小段代碼來(lái)改變目標(biāo)的樣式.創(chuàng)造rollover效果
  檢查鼠標(biāo)是否沒(méi)有放開(kāi),如果沒(méi)有
  設(shè)置curTarget代表當(dāng)前item
  記錄item的當(dāng)前位置,如果需要的話(huà),我們可以將它返回
  克隆當(dāng)前的item到dragHelper中,我們可以移動(dòng)帶陰影效果的item.
  item拷貝到dragHelper后,原有的item還在鼠標(biāo)指針下,我們必須刪除掉dragObj,這樣腳本起作用,dragObj被包含在一個(gè)容器中.
  抓取容器中所有的item當(dāng)前坐標(biāo),高度/寬度,這樣只需要記錄一次,當(dāng)item被drag時(shí),每隨mouse移動(dòng),每移鐘就會(huì)記錄成千上萬(wàn)次.
  如果沒(méi)有,不需要做任何事,因?yàn)檫@不是一個(gè)需要移動(dòng)的item
  5、檢查curTarget,它應(yīng)該包含一個(gè)被移動(dòng)的item,如果存在,進(jìn)行下面操作:

  開(kāi)始移動(dòng)帶有陰影的item,這個(gè)item就是前文所創(chuàng)建的
  檢查每個(gè)當(dāng)前容器中的container,是否鼠標(biāo)已經(jīng)移動(dòng)到這些范圍內(nèi)了
  我們檢查看一下正在拖動(dòng)的item是屬于哪個(gè)container
  放置item在一個(gè)container的某一個(gè)item之前,或者整個(gè)container之后確認(rèn)item是可見(jiàn)的
  如果鼠標(biāo)不在container中,確認(rèn)item是不可見(jiàn)了.
  6、剩下的事就是捕捉mouseUp的事件了

該文章在 2010/11/28 9:25:08 編輯過(guò)
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved