怎麼用javascript進行拖拽

Javascript的特點是dom的處理與網頁效果,大多數情況我們只用到了這個語言的最簡單的功能,比如製作圖片輪播/網頁的tab等等,這篇文章將向你展示如何在自己的網頁上製作拖拽.

有很多理由讓你的網站加入拖拽功能,最簡單的一個是數據重組.例如:你有一個序列的內容讓用戶排序,用戶需要給每個條目進行輸入或者用select選擇,替代前面這個方法的就是拖拽.或許你的網站也需要一個用戶可以拖動的導航窗口!那麼這些效果都是很簡單:因爲你可以很容易的實現!

網頁上實現拖拽其實也不是很複雜.第一你需要知道鼠標座標,第二你需要知道用戶鼠標點擊一個網頁元素並實現拖拽,最後我們要實現移動這個元素.

運行代碼框:

<SCRIPT
      src="/articleimg/2006/07/3791/drag_drop.js"
      type=text/javascript></SCRIPT>
<STYLE type=text/css>LI {
 MARGIN-BOTTOM: 10px
}
OL {
 MARGIN-TOP: 5px
}
.DragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BACKGROUND-COLOR: #eee
}
.DragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.DragDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.miniDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 FILTER: alpha(opacity=50); BACKGROUND-COLOR: #ff99cc
}
LEGEND {
 FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666699; FONT-FAMILY: verdana, tahoma, arial
}
FIELDSET {
 PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px
}
.History {
 FONT-SIZE: 10px; OVERFLOW: auto; WIDTH: 100%; FONT-FAMILY: verdana, tahoma, arial; HEIGHT: 82px
}
#DragContainer8 {
 BORDER-RIGHT: #669999 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #669999 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; BORDER-LEFT: #669999 1px solid; WIDTH: 110px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 1px solid; HEIGHT: 110px
}
.miniDragBox {
 FLOAT: left; MARGIN: 0px 5px 5px 0px; WIDTH: 20px; HEIGHT: 20px
}
PRE {
 BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #f8f8f0
}
</STYLE>
<body>
<FIELDSET id=Demo4><LEGEND>樣例- 拖拽頁面元素</LEGEND>
      <DIV>
      <DIV class=DragContainer id=DragContainer4 overclass="OverDragContainer">
      <DIV class=DragBox id=Item1 overclass="OverDragBox"
      dragclass="DragDragBox">Item #1</DIV>
      <DIV class=DragBox id=Item2 overclass="OverDragBox"
      dragclass="DragDragBox">Item #2</DIV>
      <DIV class=DragBox id=Item3 overclass="OverDragBox"
      dragclass="DragDragBox">Item #3</DIV>
      <DIV class=DragBox id=Item4 overclass="OverDragBox"
      dragclass="DragDragBox">Item #4</DIV></DIV>
      <DIV class=DragContainer id=DragContainer5 overclass="OverDragContainer">
      <DIV class=DragBox id=Item5 overclass="OverDragBox"
      dragclass="DragDragBox">Item #5</DIV>
      <DIV class=DragBox id=Item6 overclass="OverDragBox"
      dragclass="DragDragBox">Item #6</DIV>
      <DIV class=DragBox id=Item7 overclass="OverDragBox"
      dragclass="DragDragBox">Item #7</DIV>
      <DIV class=DragBox id=Item8 overclass="OverDragBox"
      dragclass="DragDragBox">Item #8</DIV></DIV>
      <DIV class=DragContainer id=DragContainer6 overclass="OverDragContainer">
      <DIV class=DragBox id=Item9 overclass="OverDragBox"
      dragclass="DragDragBox">Item #9</DIV>
      <DIV class=DragBox id=Item10 overclass="OverDragBox"
      dragclass="DragDragBox">Item #10</DIV>
      <DIV class=DragBox id=Item11 overclass="OverDragBox"
      dragclass="DragDragBox">Item #11</DIV>
      <DIV class=DragBox id=Item12 overclass="OverDragBox"
      dragclass="DragDragBox">Item #12</DIV></DIV></DIV></FIELDSET>
</body>
</html> 

獲取鼠標移動信息

第一我們需要獲取鼠標的座標.我們加一個用戶函數到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
 };
}

運行代碼框:

<script>

function mouseMove(ev){
 ev           = ev || window.event;
 var mousePos = mouseCoords(ev);
  document.getElementById('xxx').value = mousePos.x;
  document.getElementById('yyy').value = mousePos.y;
}

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

document.onmousemove = mouseMove;
</script>Mouse X Position:
<input id=xxx type=text>
<br>Mouse Y Position:
<input id=yyy type=text>

</body>
</html>

你首先要聲明一個evnet對象.不論何時你移動鼠標/點擊/按鍵等等,會對應一個event的事件.在Internet Explorer裏event是全局變量,會被存儲在window.event裏. 在firefox中,或者其他瀏覽器,event事件會被相應的自定義函數獲取.當我們將mouseMove函數賦值於document.onmousemovemouseMove會獲取鼠標移動事件.

(ev = ev || window.event) 這樣讓ev在所有瀏覽器下獲取了event事件,在Firefox下"||window.event"將不起作用,因爲ev已經有了賦值.在MSIE下ev是空的,所以ev將設置爲window.event.

因爲我們在這篇文章中需要多次獲取鼠標座標,所以我們設計了mouseCoords這個函數,它只包含了一個參數,就是the event.

我們需要運行在MSIE與Firefox爲首的其他瀏覽器下.Firefox以event.pageX和event.pageY來代表鼠標相應於文檔左上角的位置.如果你有一個500*500的窗口,而且你的鼠標在正中間,那麼paegX和pageY將是250,當你將頁面往下滾動500px,那麼pageY將是750.此時pageX不變,還是250.

MSIE和這個相反,MSIE將event.clientX與event.clientY來代表鼠標與ie窗口的位置,並不是文檔.當我們有一個500*500的窗口,鼠標在正中間,那麼clientX與clientY也是250,如果你垂直滾動窗口到任何位置,clientY仍然是250,因爲相對ie窗口並沒有變化.想得到正確的結果,我們必須加入scrollLeft與scrollTop這兩個相對於文檔鼠標位置的屬性.最後,由於MSIE並沒有0,0的文檔起始位置,因爲通常會設置2px的邊框在周圍,邊框的寬度包含在document.body.clientLeft與clientTop這兩個屬性中,我們再加入這些到鼠標的位置中.

很幸運,這樣mouseCoords函數就完成了,我們不再爲座標的事操心了.

捕捉鼠標點擊

下次我們將知道鼠標何時點擊與何時放開.如果我們跳過這一步,我們在做拖拽時將永遠不知道鼠標移動上面時的動作,這將是惱人的與違反直覺的.

這裏有兩個函數幫助我們:onmousedown與onmouseup.我們預先設置函數來接收document.onmousemove,這樣看起來很象我們會獲取document.onmousedown與document.onmouseup.但是當我們獲取document.onmousedown時,我們同時獲取了任何對象的點擊屬性如:text,images,tables等等.我們只想獲取那些需要拖拽的屬性,所以我們設置函數來獲取我們需要移動的對象.

運行代碼框:

<script>
function mouseDown(ev){
 ev         = ev || window.event;
 var target = ev.target || ev.srcElement;

 if(target.onmousedown || target.getAttribute('DragObj')){
  return false;
 }
}

function makeClickable(item){
 if(!item) return;
 item.onmousedown = function(ev){
  document.getElementById('ClickImage').value = this.name;
 }
}
document.onmousedown = mouseDown;
window.onload = function(){
 makeClickable(document.getElementById('ClickImage1'));
 makeClickable(document.getElementById('ClickImage2'));
 makeClickable(document.getElementById('ClickImage3'));
 makeClickable(document.getElementById('ClickImage4'));
}</script>

<FIELDSET id=Demo3>
<h3>
  Demo - Click any image
</h3>
<IMG id=ClickImage1
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_spade.gif"
name=Spade><IMG id=ClickImage2
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_heart.gif"
name=Heart><IMG id=ClickImage3
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_diamond.gif"
name=Diamond><IMG id=ClickImage4
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_club.gif"
 name=Club>
<BR>You clicked on: <INPUT id=ClickImage type="text"> </FIELDSET>

移動一個元素

我們知道了怎麼捕捉鼠標移動與點擊.剩下的就是移動元素了.首先,要確定一個明確的頁面位置,css樣式表要用'absolute'.設置元素絕對位置意味着我們可以用樣式表的.top和.left來定位,可以用相對位置來定位了.我們將鼠標的移動全部相對頁面top-left,基於這點,我們可以進行下一步了.

當我們定義item.style.position='absolute',所有的操作都是改變left座標與top座標,然後它移動了.

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

你會注意到這個代碼幾乎是前面的全集,將前面的合在一起就實現了拖拽效果了.

當我們點擊一個item時,我們就獲取了很多變量,如鼠標位置,鼠標位置自然就包含了那個item的座標信息了.如果我們點擊了一個20*20px圖像的正中間,那麼鼠標的相對座標爲{x:10,y:10}.當我們點擊這個圖像的左上角那麼鼠標的相對座標爲{x:0,y:0}.當我們點擊時,我們用這個方法取得一些鼠標與圖片校對的信息.如果我們不能加載頁面item,那麼信息將是document信息,會忽略了點擊的item信息.

運行代碼框:

<script>
Number.prototype.NaN0=function(){return isNaN(this)?0:this;}
var iMouseDown  = false;
var dragObject  = null;
var curTarget   = null;

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

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 + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
  top  += e.offsetTop  + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
  e     = e.offsetParent;
 }

 left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
 top  += e.offsetTop  + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);

 return {x:left, y:top};

}

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

function mouseDown(ev){
 ev         = ev || window.event;
 var target = ev.target || ev.srcElement;

 if(target.onmousedown || target.getAttribute('DragObj')){
  return false;
 }
}

function mouseUp(ev){

 dragObject = null;

 iMouseDown = false;
}


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

 /*
 We are setting target to whatever item the mouse is currently on

 Firefox uses event.target here, MSIE uses event.srcElement
 */
 var target   = ev.target || ev.srcElement;
 var mousePos = mouseCoords(ev);

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

 // track the current mouse state so we can compare against it next time
 lMouseState = iMouseDown;

 // this prevents items on the page from being highlighted while dragging
 if(curTarget || dragObject) return false;
}

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

window.onload = function() {
 makeDraggable(document.getElementById('DragImage5'));
 makeDraggable(document.getElementById('DragImage6'));
 makeDraggable(document.getElementById('DragImage7'));
 makeDraggable(document.getElementById('DragImage8'));
}
</script>

<FIELDSET id=Demo5 style="HEIGHT: 70px"><h3>Demo - Drag any of the
images</h3><IMG id=DragImage5
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_spade.gif"><IMG
id=DragImage6
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_heart.gif"><IMG
id=DragImage7
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_diamond.gif"><IMG
id=DragImage8
src="/web7ibu/UpLoadFiles/wangye/200701/28/drag_drop_club.gif"> </FIELDSET>

mouseOffset函數使用了另一個函數getPosition.getPosition的作用是返回item相對頁面左上角的座標,如果我們嘗試獲取item.offsetLeft或者item.style.left,那麼我們將取得item相對與父級的位置,不是整個document.所有的腳本我們都是相對整個document,這樣會更好一些.

 

爲了完成getPosition任務,必須循環取得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;
}

鼠標釋放時會去取是否有drop屬性,如果存在,同時鼠標指針還在drop的範圍內,執行drop操作.

    我們檢查鼠標指針位置是否在目標範圍是用(mousePos.x>targetPos.x),而且還要符合條件(mousePos.x<(targPos.x + targWidth)).

    如果所有的條件符合,說明指針確實在範圍內,可以執行drop指令了.

運行代碼框:

<SCRIPT
      src="/developer/programme/js/drag_drop.js"
      type=text/javascript></SCRIPT>
<STYLE type=text/css>LI {
 MARGIN-BOTTOM: 10px
}
OL {
 MARGIN-TOP: 5px
}
.DragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BACKGROUND-COLOR: #eee
}
.DragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.DragDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.miniDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 FILTER: alpha(opacity=50); BACKGROUND-COLOR: #ff99cc
}
LEGEND {
 FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666699; FONT-FAMILY: verdana, tahoma, arial
}
FIELDSET {
 PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px
}
.History {
 FONT-SIZE: 10px; OVERFLOW: auto; WIDTH: 100%; FONT-FAMILY: verdana, tahoma, arial; HEIGHT: 82px
}
#DragContainer8 {
 BORDER-RIGHT: #669999 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #669999 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; BORDER-LEFT: #669999 1px solid; WIDTH: 110px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 1px solid; HEIGHT: 110px
}
.miniDragBox {
 FLOAT: left; MARGIN: 0px 5px 5px 0px; WIDTH: 20px; HEIGHT: 20px
}
PRE {
 BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #f8f8f0
}
</STYLE>
<body>
<FIELDSET id=Demo4><LEGEND>樣例- 拖拽頁面元素</LEGEND>
      <DIV>
      <DIV class=DragContainer id=DragContainer4 overclass="OverDragContainer">
      <DIV class=DragBox id=Item1 overclass="OverDragBox"
      dragclass="DragDragBox">Item #1</DIV>
      <DIV class=DragBox id=Item2 overclass="OverDragBox"
      dragclass="DragDragBox">Item #2</DIV>
      <DIV class=DragBox id=Item3 overclass="OverDragBox"
      dragclass="DragDragBox">Item #3</DIV>
      <DIV class=DragBox id=Item4 overclass="OverDragBox"
      dragclass="DragDragBox">Item #4</DIV></DIV>
      <DIV class=DragContainer id=DragContainer5 overclass="OverDragContainer">
      <DIV class=DragBox id=Item5 overclass="OverDragBox"
      dragclass="DragDragBox">Item #5</DIV>
      <DIV class=DragBox id=Item6 overclass="OverDragBox"
      dragclass="DragDragBox">Item #6</DIV>
      <DIV class=DragBox id=Item7 overclass="OverDragBox"
      dragclass="DragDragBox">Item #7</DIV>
      <DIV class=DragBox id=Item8 overclass="OverDragBox"
      dragclass="DragDragBox">Item #8</DIV></DIV>
      <DIV class=DragContainer id=DragContainer6 overclass="OverDragContainer">
      <DIV class=DragBox id=Item9 overclass="OverDragBox"
      dragclass="DragDragBox">Item #9</DIV>
      <DIV class=DragBox id=Item10 overclass="OverDragBox"
      dragclass="DragDragBox">Item #10</DIV>
      <DIV class=DragBox id=Item11 overclass="OverDragBox"
      dragclass="DragDragBox">Item #11</DIV>
      <DIV class=DragBox id=Item12 overclass="OverDragBox"
      dragclass="DragDragBox">Item #12</DIV></DIV></DIV></FIELDSET>
</body>
</html>

Pulling It All Together

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

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

下一步我們將通過"假代碼"讓reader看到真代碼,下面爲推薦:

1、當document第一次載入時,創建dragHelper DIV.dragHelper將給移動的item加陰影.真實的item沒有被dragged,只是用了insertBefor和appendChild來移動了,我們隱藏了dragHelper

2、有了mouseDown與mouseUp函數.所有的操作會對應到當到iMouseDown的狀態中,只有當mouse左鍵爲按下時iMouseDown才爲真,否則爲假.

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

4、現在我們的代碼知道每個item的加入,當我們移動處mouseMove,mouseMove函數首先會設置變量target,鼠標移動在上面的item,如果這個item在容器中(checked with getAttribute):

  • 運行一小段代碼來改變目標的樣式.創造rollover效果
  • 檢查鼠標是否沒有放開,如果沒有
    • 設置curTarget代表當前item
    • 記錄item的當前位置,如果需要的話,我們可以將它返回
    • 克隆當前的item到dragHelper中,我們可以移動帶陰影效果的item.
    • item拷貝到dragHelper後,原有的item還在鼠標指針下,我們必須刪除掉dragObj,這樣腳本起作用,dragObj被包含在一個容器中.
    • 抓取容器中所有的item當前座標,高度/寬度,這樣只需要記錄一次,當item被drag時,每隨mouse移動,每移鍾就會記錄成千上萬次.
  • 如果沒有,不需要做任何事,因爲這不是一個需要移動的item

5、檢查curTarget,它應該包含一個被移動的item,如果存在,進行下面操作:

  • 開始移動帶有陰影的item,這個item就是前文所創建的
  • 檢查每個當前容器中的container,是否鼠標已經移動到這些範圍內了
    • 我們檢查看一下正在拖動的item是屬於哪個container
    • 放置item在一個container的某一個item之前,或者整個container之後
    • 確認item是可見的
  • 如果鼠標不在container中,確認item是不可見了.

6、剩下的事就是捕捉mouseUp的事件了

你現在擁有了拖拽的所有東西.

下面的三個demo是記錄事件歷史.當你的鼠標在item上移動,將記錄所生的事件.

如果你不明白可以嘗試一下鼠標的劃過或者拖動,看有什麼發生.

運行代碼框:

<STYLE>LI {
 MARGIN-BOTTOM: 10px
}
OL {
 MARGIN-TOP: 5px
}
.DragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
 BACKGROUND-COLOR: #eee
}
.DragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.DragDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.miniDragBox {
 BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
 FILTER: alpha(opacity=50); BACKGROUND-COLOR: #ff99cc
}
LEGEND {
 FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666699; FONT-FAMILY: verdana, tahoma, arial
}
FIELDSET {
 PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px
}
.History {
 FONT-SIZE: 10px; OVERFLOW: auto; WIDTH: 100%; FONT-FAMILY: verdana, tahoma, arial; HEIGHT: 82px
}
#DragContainer8 {
 BORDER-RIGHT: #669999 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #669999 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; BORDER-LEFT: #669999 1px solid; WIDTH: 110px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 1px solid; HEIGHT: 110px
}
.miniDragBox {
 FLOAT: left; MARGIN: 0px 5px 5px 0px; WIDTH: 20px; HEIGHT: 20px
}
pre{border:1 solid #CCC;background-color:#F8F8F0;padding:10px;}
</STYLE>


<script>

// iMouseDown represents the current mouse button state: up or down
/*
lMouseState represents the previous mouse button state so that we can
check for button clicks and button releases:

if(iMouseDown && !lMouseState) // button just clicked!
if(!iMouseDown && lMouseState) // button just released!
*/
var mouseOffset = null;
var iMouseDown  = false;
var lMouseState = false;
var dragObject  = null;

// Demo 0 variables
var DragDrops   = [];
var curTarget   = null;
var lastTarget  = null;
var dragHelper  = null;
var tempDiv     = null;
var rootParent  = null;
var rootSibling = null;

Number.prototype.NaN0=function(){return isNaN(this)?0:this;}

function CreateDragContainer(){
 /*
 Create a new "Container Instance" so that items from one "Set" can not
 be dragged into items from another "Set"
 */
 var cDrag        = DragDrops.length;
 DragDrops[cDrag] = [];

 /*
 Each item passed to this function should be a "container".  Store each
 of these items in our current container
 */
 for(var i=0; i<arguments.length; i++){
  var cObj = arguments[i];
  DragDrops[cDrag].push(cObj);
  cObj.setAttribute('DropObj', cDrag);

  /*
  Every top level item in these containers should be draggable.  Do this
  by setting the DragObj attribute on each item and then later checking
  this attribute in the mouseMove function
  */
  for(var j=0; j<cObj.childNodes.length; j++){

   // Firefox puts in lots of #text nodes...skip these
   if(cObj.childNodes[j].nodeName=='#text') continue;

   cObj.childNodes[j].setAttribute('DragObj', cDrag);
  }
 }
}


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

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 + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
  top  += e.offsetTop  + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
  e     = e.offsetParent;
 }

 left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
 top  += e.offsetTop  + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);

 return {x:left, y:top};

}


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

 /*
 We are setting target to whatever item the mouse is currently on

 Firefox uses event.target here, MSIE uses event.srcElement
 */
 var target   = ev.target || ev.srcElement;
 var mousePos = mouseCoords(ev);

 // mouseOut event - fires if the item the mouse is on has changed
 if(lastTarget && (target!==lastTarget)){
  // reset the classname for the target element
  var origClass = lastTarget.getAttribute('origClass');
  if(origClass) lastTarget.className = origClass;
 }

 /*
 dragObj is the grouping our item is in (set from the createDragContainer function).
 if the item is not in a grouping we ignore it since it can't be dragged with this
 script.
 */
 var dragObj = target.getAttribute('DragObj');

  // if the mouse was moved over an element that is draggable
 if(dragObj!=null){

  // mouseOver event - Change the item's class if necessary
  if(target!=lastTarget){
   var oClass = target.getAttribute('overClass');
   if(oClass){
    target.setAttribute('origClass', target.className);
    target.className = oClass;
   }
  }

  // if the user is just starting to drag the element
  if(iMouseDown && !lMouseState){
   // mouseDown target
   curTarget     = target;

   // Record the mouse x and y offset for the element
   rootParent    = curTarget.parentNode;
   rootSibling   = curTarget.nextSibling;

   mouseOffset   = getMouseOffset(target, ev);

   // We remove anything that is in our dragHelper DIV so we can put a new item in it.
   for(var i=0; i<dragHelper.childNodes.length; i++) dragHelper.removeChild(dragHelper.childNodes[i]);

   // Make a copy of the current item and put it in our drag helper.
   dragHelper.appendChild(curTarget.cloneNode(true));
   dragHelper.style.display = 'block';

   // set the class on our helper DIV if necessary
   var dragClass = curTarget.getAttribute('dragClass');
   if(dragClass){
    dragHelper.firstChild.className = dragClass;
   }

   // disable dragging from our helper DIV (it's already being dragged)
   dragHelper.firstChild.removeAttribute('DragObj');

   /*
   Record the current position of all drag/drop targets related
   to the element.  We do this here so that we do not have to do
   it on the general mouse move event which fires when the mouse
   moves even 1 pixel.  If we don't do this here the script
   would run much slower.
   */
   var dragConts = DragDrops[dragObj];

   /*
   first record the width/height of our drag item.  Then hide it since
   it is going to (potentially) be moved out of its parent.
   */
   curTarget.setAttribute('startWidth',  parseInt(curTarget.offsetWidth));
   curTarget.setAttribute('startHeight', parseInt(curTarget.offsetHeight));
   curTarget.style.display  = 'none';

   // loop through each possible drop container
   for(var i=0; i<dragConts.length; i++){
    with(dragConts[i]){
     var pos = getPosition(dragConts[i]);

     /*
     save the width, height and position of each container.

     Even though we are saving the width and height of each
     container back to the container this is much faster because
     we are saving the number and do not have to run through
     any calculations again.  Also, offsetHeight and offsetWidth
     are both fairly slow.  You would never normally notice any
     performance hit from these two functions but our code is
     going to be running hundreds of times each second so every
     little bit helps!

     Note that the biggest performance gain here, by far, comes
     from not having to run through the getPosition function
     hundreds of times.
     */
     setAttribute('startWidth',  parseInt(offsetWidth));
     setAttribute('startHeight', parseInt(offsetHeight));
     setAttribute('startLeft',   pos.x);
     setAttribute('startTop',    pos.y);
    }

    // loop through each child element of each container
    for(var j=0; j<dragConts[i].childNodes.length; j++){
     with(dragConts[i].childNodes[j]){
      if((nodeName=='#text') || (dragConts[i].childNodes[j]==curTarget)) continue;

      var pos = getPosition(dragConts[i].childNodes[j]);

      // save the width, height and position of each element
      setAttribute('startWidth',  parseInt(offsetWidth));
      setAttribute('startHeight', parseInt(offsetHeight));
      setAttribute('startLeft',   pos.x);
      setAttribute('startTop',    pos.y);
     }
    }
   }
  }
 }

 // If we get in here we are dragging something
 if(curTarget){
  // move our helper div to wherever the mouse is (adjusted by mouseOffset)
  dragHelper.style.top  = mousePos.y - mouseOffset.y;
  dragHelper.style.left = mousePos.x - mouseOffset.x;

  var dragConts  = DragDrops[curTarget.getAttribute('DragObj')];
  var activeCont = null;

  var xPos = mousePos.x - mouseOffset.x + (parseInt(curTarget.getAttribute('startWidth')) /2);
  var yPos = mousePos.y - mouseOffset.y + (parseInt(curTarget.getAttribute('startHeight'))/2);

  // check each drop container to see if our target object is "inside" the container
  for(var i=0; i<dragConts.length; i++){
   with(dragConts[i]){
    if(((getAttribute('startLeft'))                               < xPos) &&
     ((getAttribute('startTop'))                                < yPos) &&
     ((getAttribute('startLeft') + getAttribute('startWidth'))  > xPos) &&
     ((getAttribute('startTop')  + getAttribute('startHeight')) > yPos)){

      /*
      our target is inside of our container so save the container into
      the activeCont variable and then exit the loop since we no longer
      need to check the rest of the containers
      */
      activeCont = dragConts[i];

      // exit the for loop
      break;
    }
   }
  }

  // Our target object is in one of our containers.  Check to see where our div belongs
  if(activeCont){
   // beforeNode will hold the first node AFTER where our div belongs
   var beforeNode = null;

   // loop through each child node (skipping text nodes).
   for(var i=activeCont.childNodes.length-1; i>=0; i--){
    with(activeCont.childNodes[i]){
     if(nodeName=='#text') continue;

     // if the current item is "After" the item being dragged
     if(
      curTarget != activeCont.childNodes[i]                              &&
      ((getAttribute('startLeft') + getAttribute('startWidth'))  > xPos) &&
      ((getAttribute('startTop')  + getAttribute('startHeight')) > yPos)){
       beforeNode = activeCont.childNodes[i];
     }
    }
   }

   // the item being dragged belongs before another item
   if(beforeNode){
    if(beforeNode!=curTarget.nextSibling){
     activeCont.insertBefore(curTarget, beforeNode);
    }

   // the item being dragged belongs at the end of the current container
   } else {
    if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)){
     activeCont.appendChild(curTarget);
    }
   }

   // make our drag item visible
   if(curTarget.style.display!=''){
    curTarget.style.display  = '';
   }
  } else {

   // our drag item is not in a container, so hide it.
   if(curTarget.style.display!='none'){
    curTarget.style.display  = 'none';
   }
  }
 }

 // track the current mouse state so we can compare against it next time
 lMouseState = iMouseDown;

 // mouseMove target
 lastTarget  = target;

 // track the current mouse state so we can compare against it next time
 lMouseState = iMouseDown;

 // this helps prevent items on the page from being highlighted while dragging
 return false;
}

function mouseUp(ev){
 if(curTarget){
  // hide our helper object - it is no longer needed
  dragHelper.style.display = 'none';

  // if the drag item is invisible put it back where it was before moving it
  if(curTarget.style.display == 'none'){
   if(rootSibling){
    rootParent.insertBefore(curTarget, rootSibling);
   } else {
    rootParent.appendChild(curTarget);
   }
  }

  // make sure the drag item is visible
  curTarget.style.display = '';
 }
 curTarget  = null;
 iMouseDown = false;
}

function mouseDown(){
 iMouseDown = true;
 if(lastTarget){
  return false;
 }
}

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

window.onload = function(){
 // Create our helper object that will show the item while dragging
 dragHelper = document.createElement('DIV');
 dragHelper.style.cssText = 'position:absolute;display:none;';
  
 CreateDragContainer(
  document.getElementById('DragContainer1'),
  document.getElementById('DragContainer2'),
  document.getElementById('DragContainer3')
 );

 document.body.appendChild(dragHelper);
}

</script>

<!--the mouse over and dragging class are defined on each item-->

<div class="DragContainer" id="DragContainer1">
 <div class="DragBox" id="Item1"  overClass="OverDragBox" dragClass="DragDragBox">Item #1</div>
 <div class="DragBox" id="Item2"  overClass="OverDragBox" dragClass="DragDragBox">Item #2</div>
 <div class="DragBox" id="Item3"  overClass="OverDragBox" dragClass="DragDragBox">Item #3</div>
 <div class="DragBox" id="Item4"  overClass="OverDragBox" dragClass="DragDragBox">Item #4</div>
</div>
<div class="DragContainer" id="DragContainer2">
 <div class="DragBox" id="Item5"  overClass="OverDragBox" dragClass="DragDragBox">Item #5</div>
 <div class="DragBox" id="Item6"  overClass="OverDragBox" dragClass="DragDragBox">Item #6</div>
 <div class="DragBox" id="Item7"  overClass="OverDragBox" dragClass="DragDragBox">Item #7</div>
 <div class="DragBox" id="Item8"  overClass="OverDragBox" dragClass="DragDragBox">Item #8</div>
</div>
<div class="DragContainer" id="DragContainer3">
 <div class="DragBox" id="Item9"  overClass="OverDragBox" dragClass="DragDragBox">Item #9</div>
 <div class="DragBox" id="Item10" overClass="OverDragBox" dragClass="DragDragBox">Item #10</div>
 <div class="DragBox" id="Item11" overClass="OverDragBox" dragClass="DragDragBox">Item #11</div>
 <div class="DragBox" id="Item12" overClass="OverDragBox" dragClass="DragDragBox">Item #12</div>

三個demo是記錄事件歷史合成後的效果請查看

示例:類似Google個性化主頁,實現Web桌面託拽的實例

我們看過 

    ·MSN
    ·MicroSoft Live
    ·GOOGLE個性主頁 
    等web頁面元素可拖動並放置的例子,給我們新奇的體驗。 
    這個專題將討論它們的實現方法原理及一些實例。 
    實現這個效果要用到的一些事件及過程:
 
·引發事件對象
·控制對象根節點
·是否抓起
·空臨時層
·鼠標與控件的相對座標
·窗體加載時委託到Prepare
·生成臨時層,並設置其屬性
·獲得控制對象的根節點元素
·當鼠標在文檔上移動時事件委託到MoveIt
·當鼠標按下時事件委託到Drag
·當鼠標釋放擡起時事件委託到Release
 
    關於理論研究:
 
 
 
    關於一些實例:
 

 

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章