- 1、js怎麼實現一個拖拽事件
- 2、js實現圖片拖動代碼,希望大神給代碼詳細的注釋(解釋)下。
- 3、js實現div的拖拽
- 4、js鼠標拖動div
Javascript的特點是dom的處理與網頁效果,大多數情況我們只用到了這個語言的最簡單的功能,比如製作圖片輪播/網頁的tab等等,這篇文章將向你展示如何在自己的網頁上製作拖拽.
有很多理由讓你的網站加入拖拽功能,最簡單的一個是數據重組.例如:你有一個序列的內容讓用戶排序,用戶需要給每個條目進行輸入或者用select 選擇,替代前面這個方法的就是拖拽.或許你的網站也需要一個用戶可以拖動的導航窗口!那麼這些效果都是很簡單:因為你可以很容易的實現!
網頁上實現拖拽其實也不是很複雜.第一你需要知道鼠標坐標,第二你需要知道用戶鼠標點擊一個網頁元素並實現拖拽,最後我們要實現移動這個元素.
獲取鼠標移動信息
第一我們需要獲取鼠標的坐標.我們加一個用戶函數到document.onmousemove就可以了:
Java代碼 收藏代碼
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
};
}
你首先要聲明一個evnet對象.不論何時你移動鼠標/點擊/按鍵等等,會對應一個event的事件.在Internet Explorer里event是全局變量,會被存儲在window.event里. 在firefox中,或者其他瀏覽器,event事件會被相應的自定義函數獲取.當我們將mouseMove函數賦值於document.onmousemove,mouseMove會獲取鼠標移動事件.
(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等等.我們只想獲取那些需要拖拽的屬性,所以我們設置函數來獲取我們需要移動的對象.
移動一個元素
我們知道了怎麼捕捉鼠標移動與點擊.剩下的就是移動元素了.首先,要確定一個明確的頁面位置,css樣式表要用’absolute’.設置元素絕對位置意味着我們可以用樣式表的.top和.left來定位,可以用相對位置來定位了.我們將鼠標的移動全部相對頁面top-left,基於這點,我們可以進行下一步了.
當我們定義item.style.position=’absolute’,所有的操作都是改變left坐標與top坐標,然後它移動了.
Java代碼 收藏代碼
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信息.
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,然後放在鼠標釋放的位置.這個解決方案,也是因為美學原因不予接受.
最後的解決方案是,我們並不去除拖拽效果.這種方法比前兩種繁雜許多,我們需要定義我們需要釋放目標的列表,當鼠標釋放時,手工去檢查釋放的位置是否是在目標列表位置上,如果在,說明是釋放在目標位置上了.
Java代碼 收藏代碼
/*
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; idropTargets.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.xtargetPos.x),而且還要符合條件(mousePos.x(targPos.x + targWidth)).如果所有的條件符合,說明指針確實在範圍內,可以執行drop指令了.
Pulling It All Together
最後我們擁有了所有的drag/drop的腳本片斷!下一個事情是我們將創建一個DOM處理.
下面的代碼將創建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效果
* 檢查鼠標是否沒有放開,如果沒有
o 設置curTarget代表當前item
o 記錄item的當前位置,如果需要的話,我們可以將它返回
o 克隆當前的item到dragHelper中,我們可以移動帶陰影效果的item.
o item拷貝到dragHelper後,原有的item還在鼠標指針下,我們必須刪除掉dragObj,這樣腳本起作用,dragObj被包含在一個容器中.
o 抓取容器中所有的item當前坐標,高度/寬度,這樣只需要記錄一次,當item被drag時,每隨mouse移動,每移鍾就會記錄成千上萬次.
* 如果沒有,不需要做任何事,因為這不是一個需要移動的item
5、檢查curTarget,它應該包含一個被移動的item,如果存在,進行下面操作:
* 開始移動帶有陰影的item,這個item就是前文所創建的
* 檢查每個當前容器中的container,是否鼠標已經移動到這些範圍內了
o 我們檢查看一下正在拖動的item是屬於哪個container
o 放置item在一個container的某一個item之前,或者整個container之後
o 確認item是可見的
* 如果鼠標不在container中,確認item是不可見了.
!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “”
html xmlns=”” xml:lang=”en”
head
meta http-equiv=”Content-Type” content=”text/html;charset=UTF-8″
titleDocument/title
/head
body
div id=”box1″ style = ‘width:100px; height: 100px; background:#ccc; position:fixed;’/div
!– 注意 盒子一定要定位 position:fixed; 或者 position:absolute;–
/body
script type=”text/javascript”
function getPos(e){//這是一個 獲取鼠標位置的函數
var oEvent = e || event;
return {x: oEvent.clientX + document.documentElement.scrollLeft || document.body.scrollLeft,
y: oEvent.clientY +document.documentElement.scrollTop || document.body.scrollTop};
}
document.getElementById(‘box1’).onmousedown = function(e){ //你要拖動對象在mousedown的時候發生的事情
var oEvent = e || event;
var pos = getPos(oEvent);
var _this = this;
_this.style.cursor = ‘move’;//改變鼠標狀態
_this.disY = pos.y – _this.offsetTop;
_this.disX = pos.x – _this.offsetLeft;
document.onmousemove =function(e){ //在鼠標按下的時候 並且 移動的時候 發生的事情
var oEvent = e || event;
var dpos = getPos(oEvent);
var t = dpos.y-_this.disY ; //移動的時候獲取的 移動 top值
var l = dpos.x-_this.disX ;//移動的時候獲取的 移動 left
_this.style.top=t + “px”; //這兩條給盒子賦值
_this.style.left=l + “px”;
};
document.onmouseup = function(){//鼠標彈起的時候做的事情 一些釋放 操作
_this.style.cursor = ‘pointer’
this.onmousemove = null;
this.onmouseup = null;
try{
_this.releaseCapture();}catch(e){}
};
try{
_this.setCapture();}catch(b){} //這裡是為了 讓盒子拖動的時候不要複製頁面裏面的其他內容
return false;
};
/script
/html
div id=”c” onmousedown=”mm(event);”123123/div
evt參數是就是上面的event對象;
Event 對象代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。
因為火狐不支持直接獲取event對象.因此FF在觸發拖拽事件前需要明確傳遞event.
IE則不需要.所以才出現 e = evt || event; 主要是兼容所用.
e.clientX是獲取當前鼠標的橫坐標.
你的obj.style.left是獲取不到的因為該div沒有設置style屬性所以只要將樣式改為行內就行了
!DOCTYPE html
html lang=”en”
head
meta charset=”UTF-8″
title文哥討厭IE/title
/head
body
div id=”over” onmousedown=”down(this,event)” style=”width:100px;height:30px;background:red;position:absolute;left:20px;top:500px;” onmousemove=”move(this,event)” onmouseup=”seup(this,event)”
/div
script type=”text/javascript”
var posX,posY;
var downX,downY;
var mark=false;
function down(obj,event)
{
obj.style.cursor=”move”;
posX=obj.style.left;
posY=obj.style.top;
downX=event.clientX;
downY=event.clientY;
mark=true;
///alert(posX);
///alert(posY);
}
function move(obj,event)
{
var moveX=event.clientX;
var moveY=event.clientY;
if (mark) {
obj.style.left=parseInt(moveX) + parseInt(posX) – parseInt(downX) + “px”;
obj.style.top=parseInt(moveY) + parseInt(posY) – parseInt(downY)+ “px”;
}
}
function seup(obj,event)
{
if (mark) {
var moveX=event.clientX;
var moveY=event.clientY;
obj.style.left=parseInt(moveX) + parseInt(posX) – parseInt(downX)+ “px”;
obj.style.top=parseInt(moveY) + parseInt(posY) – parseInt(downY)+ “px”;
downX=moveX;
downY=moveY;
}
obj.style.cursor=”default”;
mark = false;
}
/script
/body
/html
原創文章,作者:WADYJ,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/127226.html