一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

javascript 拖放效果實現代碼

有許多理由讓你在頁面中加入拖放的功能,其中最簡單的理由是重新組織數據。舉個例子,你可能希望用戶能夠重組一系列的頁面元素,通過放置一個input或 select組件在各個元素的旁邊來代表它們的順序是一種解決方案,使該組元素可以被拖放是一種替代方案。或者也許你想在網站上擁有一個可以被用戶移動的導航窗口。這些都是使用拖放功能的簡單理由,因為你能夠實現!
在你的網頁上實現拖放的效果并不是很復雜。首先,我們知道鼠標的位置,然后我們需要了解用戶什么時候點擊一個元素,以至于我們知道要準備開始拖動它,最后我們要移動這個元素。

捕獲鼠標的移動
第一步,我們需要獲取鼠標的坐標,通過一個函數并賦給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
};
}

首先我們需要解釋一下event對象。不論你什么時候移動、點擊鼠標,或按鍵,等等,一個事件都會發生。在IE中,這個事件是全局的,它被存儲在 window.event中,對于Firefox,及其他的瀏覽器來說,這個事件將被傳遞到任何指向這個頁面動作的函數中。因此,我們使 document.onmousemove指向鼠標移動的函數,鼠標移動的函數獲得事件對象。
上述代碼中,ev在所有瀏覽器環境中都包含了event對象。在Firefox里,"||window.event"將被忽略,因為它已經包含事件。在IE中,ev的值為空,以至于需要將它的值設置為window.event。
本文中我們需要多次捕獲到鼠標的坐標,因此我們寫了一個mouseCoords方法,它有一個參數:event。
我們要再次討論IE和其他瀏覽器之間的差異。Firefox和其他的瀏覽器使用event.pageX和event.pageY來表示鼠標相對于 document文檔的位置。如果你有一個500*500的窗口,并且鼠標位于窗口中間,那么pageX和pageY的值將都是250。如果你將窗口向下滾動500象素,pageY的值為750。
如此相反的是,微軟的IE使用event.clientX和event.clientY來表示鼠標相對于window窗口的位置,而不是當前 document文檔。在相同的例子中,如果將鼠標放置于500*500窗口的中間,clientX和clientY值將均為250。如果向下滾動頁面, clientY將仍為250,因為它是相對于window窗口來測量,而不是當前的document文檔。因此,在鼠標位置中,我們應該引入 document文檔body區域的scrollLeft和scrollTop屬性。最后,IE中document文檔實際并不在(0,0)的位置,在它周圍有一個小(通常有2px)邊框,document.body.clientLeft和document.body.clientTop包含了這個邊框的寬度,從而還需要在鼠標位置中引入它們。
幸運的是,現在我們擁有了mouseCoords函數,不用再為獲取鼠標位置擔心了。

捕獲鼠標的點擊
下一步,我們必須知道鼠標何時點擊及何時釋放。如果我們跳過這一步,只要你的鼠標移動經過這些元素時,都將產生拖動這些元素的效果,這是令人討厭并違反人的直覺的。
在這里,有兩個函數可以幫助我們:onmousedown和onmouseup。先前我們已將document.onmousemove指向一個函數,因此從邏輯上似乎應該使document.onmousedown和document.onmouseup都指向函數。如果我們讓 document.onmousedown指向一個函數,那么這個函數將會因為鼠標點擊任何元素而執行:文本、圖像、表格,等等。我們只想頁面中特定的元素具有被拖放的功能,因此,我們可以通過如下方法實現:

代碼
復制代碼 代碼如下:
document.onmouseup = mouseUp;
var dragObject = null;
function makeClickable(object) {
object.onmousedown = function() {
dragObject = this;
}
}
function mouseUp(ev) {
dragObject = null;
}

我們現在有了一個變量dragObject,包含了你點擊的任何元素。當你釋放鼠標的時候,dragObject被設置為空,從而在dragObject非空的時候,我們需要進行拖動操作。

移動元素
我們現在已經知道如何捕獲鼠標移動和點擊。接下來需要做的就是移動任何我們想拖動的元素。首先,將一個元素準確移動到頁面上我們想要的位置,該元素樣式表的position值必須為absolute,這意味著你可以設置它的style.top或style.left,測量值相對于頁面的左上角,因為我們所有的鼠標移動都是相對于頁面左上角的,通常都是這樣。
一旦我們設置了item.style.position='absolute',接下來就需要改變該元素top和left的位置,使它移動

代碼
復制代碼 代碼如下:
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 ;
}
}

你會注意到這些代碼是以我們前面的例子為基礎的(參考上篇文章),將它們放置在一起,你將能夠隨意的去移動元素。
當我們點擊一個元素時,存儲了另外的一個變量,mouseOffset。mouseOffset簡單的包含了我們點擊元素的位置信息。如果我們有一張 20*20px的圖像,然后點擊圖像的中間,mouseOffset應該是{x:10, y:10}。如果我們點擊圖像的左上角,mouseOffset應為{x:0, y:0}。我們在鼠標移動后的位置信息中用到它。如果我們沒有存儲這個值,不論你點擊元素的哪一個位置,元素相對于鼠標的位置都將會是相同的。
mouseOffset函數用到了另外一個函數getPosition。getPosition目的是返回元素相對于documemt文檔的坐標位置。如果我們簡單的去讀取item.offsetLeft或item.style.left,得到的將是元素相對于它父元素的位置,而不是document文檔的。在我們的腳本中,所有的元素都是相對于document文檔的,因此需要這樣做。
要完成獲取元素相對于document文檔位置的工作,getPosition從它自身的父級開始,循環獲取它的left和top的值并累加,這樣我們就得到了我們想要的元素距文檔頂部和左側的累計值。
當我們獲取了這條信息并移動鼠標的時候,mouseMove開始運行。首先我們需要保證item.style.position值為absolute,接著,我們將元素移動到任何一個地方,鼠標位置都會減去我們之前記錄的鼠標相對于元素的偏移量。當鼠標釋放時,dragObject將被設置為null,并且mouseMove函數不再做任何事情。

放置元素
我們前面的例子已經處理了這個問題,僅僅是拖動一個元素,然后將它放下。然后,在我們放下元素的時候通常還有其他的目的,我們以拖動元素到垃圾回收站為例,或我們可能想讓該元素和頁面中某個特定的區域對齊。
不幸的是我們在這里進入了一個相對主要的問題。因為我們正在移動的元素總是直接處于我們的鼠標下,而不可能去引發mouseover、 mousedown、mouseup或鼠標對頁面中其他元素的操作。如果你移動一個元素到垃圾回收站,你的鼠標會一直在移動元素的上方,而不是垃圾回收站。
那么我們該如何處理這個問題呢?這里有幾種解決方案。在前面所提到的mouseOffset的目的是保證元素總是在鼠標下方正確的位置,如果你忽視了這點,然后總是使得元素在鼠標的右下方,你的鼠標將不會被你正在拖動的元素所隱藏,我們也不會碰到問題。但事實上往往不會這樣,為了美觀我們通常要保持元素在鼠標的下方。
另外一種選擇是不移動你正在拖動的元素,你可以改變鼠標樣式,來告訴使用者你正在拖動一個元素,直到你將它放置到某個地方。這解決了我們的問題,但是帶來了和前面一種方案面臨的同樣問題:美觀。
我們最后的一種解決方案既不影響你正在移動的元素,也不影響移動終點位置上的元素(例如垃圾回收站)。不幸的是,這比前面兩種解決方案的難度更大。我們將要做的是獲得一組我們要放置的目標,當鼠標釋放時,我們手工檢查當前鼠標相對于每個目標的位置,看鼠標是否釋放在這個目標中某一個目標的位置上,如果是的,我們就知道我們已經將元素放置在我們的目標上了。

代碼
復制代碼 代碼如下:
/*
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. < (targPos.x + targWidth)) &&
(mousePos.y > targPos.y) &&
(mousePos.y < (targPos.y + targHeight))) {
// dragObject was dropped onto curTarget!
}
}
dragObject = null ;
}


這個例子中當鼠標釋放時,我們循環每個可能放置元素的目標,如果鼠標指針在目標上,我們則擁有了一個放置元素的事件,通過鼠標橫坐標大于目標元素左側橫坐標(mousePos.x>targPos.x),小于目標元素右側橫坐標(mousePos.x<(targPos.x+ targWidth))來判定,對于Y坐標我們做同樣的判斷。如果所有的這些值都返回true,那么我們的鼠標就是在目標元素的范圍內。

整合所有的功能
最后我們使用所有代碼片斷,來創建一個完整的拖放函數腳本。我們所要做的第一件事情是DOM操作,如果你對此并不十分熟悉,可以閱讀《JavaScript Primer on DOM Manipulation》。
接下來的代碼創建容器和容器組,使得在這些容器中可以拖動每個元素,這在本文第二個demo的基礎上來完成。這段代碼能夠用來重新規劃元素的順序,將導航窗口放在頁面的左側或右側,或再加入你所能想到的其他的功能。
我們將使用偽代碼來一步步進行講解,將真實的代碼通過注釋的方式留給讀者查看。
1.當文檔第一次被加載時,我們創建一個名為dragHelper的DIV標簽,當我們開始移動一個元素的時候,dragHelper將成為一個隱藏元素,可以四處移動。真實的元素并不會被拖動,僅僅使用insertBefore和appendChild來移動。我們在開始的時候隱藏dragHelper。
2.我們創建mouseDown和mouseUp函數。起初,所有的這些函數都假設記錄了鼠標按鈕的狀態,以至于iMouseDown變量在鼠標按下的時候為true,沒有按下的時候為false。
3.我們創建一個全局變量DragDrops,以及一個函數CreateDragContainer。DragDrops包含一組相互關聯的容器。傳入CreateDragContainer的任何變量(代表容器)被組織成一個新的集合,使元素能夠在這些容器間自由移動。通過setAttribute,CreateDragContainer函數同樣將各容器中的元素綁定在一起。
4.現在我們的代碼知道每個元素所在的集合,現在來看mouseMove函數。mouseMove函數首先設置了一個變量target,表示鼠標下面的目標元素,如果這個元素在集合(用getAttribute判斷)中就繼續下面操作:
4.1.首先,在必要的時候,我們運行一個簡單的腳本來改變目標元素的class屬性,這樣就創造了一個翻動的效果。
4.2.然后我們檢查鼠標是否點擊(因為我們的代碼已經運行到這里),如果事件發生:
4.2.1.設置變量curTarget為當前元素。
4.2.2.記錄元素當前在文檔中的位置,以便在需要的時候可以將它的值取回。
4.2.3.將當前元素克隆到dragHelper,使得我們能夠移動元素的隱藏備份。
4.2.4.因為在dragHelper中我們完全擁有了拖動元素的一個備份,這個元素會始終在鼠標下,我們必須移除dragObj屬性,讓代碼知道dragObj已不在集合中。
4.2.5.我們快速記錄集合中每個元素當前的位置、寬度和高度。當元素第一次開始被拖動時,我們僅需做一次這種工作,否則每當鼠標移動的時候我們都必須做一次,甚至一秒內幾百次。
4.3.如果鼠標沒有點擊,要么我們和之前擁有同樣的目標元素,要么沒有目標元素,不論哪種情況我們都不會做任何事情。
5.現在我們檢查curTarget變量。curTarget應該僅包含一個被拖動的對象,因此如果它存在,表示我們正在拖動一個元素:
5.1.移動隱藏DIV到鼠標,這個元素和文章前面所創建的元素一樣能夠被拖動。
5.2.然后我們檢查鼠標是否存在于當前集合中每個容器中。
5.2.1.如果鼠標在某個容器中,我們檢查容器中的每個元素,查看我們正拖動的元素屬于哪個位置。
5.2.2.然后我們將所拖動的元素放置在容器中另一個元素的前面,或容器的最后位置。
5.2.3.最后我們確定元素可見。
6.剩下的事情就是捕獲mouseUp事件:
6.1.首先需要隱藏dragHelper:它不再被需要,因為我們沒有拖動任何東西。
6.2.如果拖動的元素是可見的,它已經存在于任何它所屬的容器中,所有工作已完成。
6.3.如果拖動的元素不可見,我們將它放回它原來所在的地方。

JavaScript技術javascript 拖放效果實現代碼,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 久久精品久 | 国产精品美女久久久久网 | 国产欧美亚洲精品综合在线 | 99精品国产兔费观看66 | 91精品国产99久久 | 久视频免费精品6 | 亚洲国产精品一区二区三区在线观看 | 久久久小视频 | 香蕉成人影院 | 成人精品一区二区久久 | 欧美日韩一区妖精视频yjsp | a高清免费毛片久久 | 成人国产精品999视频 | 久久久久久久久一级毛片 | 欧美在线网站 | 亚洲小说图片视频 | 99pao成人国产永久免费视频 | 不卡一区二区三区四区 | 黄大色黄美女精品大毛片 | 国产成人综合精品一区 | 九九久久免费视频 | 久久久久久中文字幕 | 国产精品亚洲综合色拍 | 国产社区| 超级色的网站观看在线 | h视频免费观看 | 免费视频一区二区 | 欧美日韩中文亚洲另类春色 | 亚洲一区二区三区精品国产 | 国产久热香蕉在线观看 | 日韩激情在线播放 | 在线观看国产黄色 | 在线亚洲欧美性天天影院 | 激情都市亚洲 | 欧美亚洲高清日韩成人 | 亚洲首页国产精品丝袜 | 2021国产情侣真实露脸在线 | 国产91久久精品一区二区 | 国产精品亚洲四区在线观看 | 狠狠久久久久综合网 | 美女毛片视频 |