js原生事件系統與坐標系統


今天來實現一個可兼容的js原生拖拽,在這里面我將會講到:

1.封裝兼容性的事件系統。

2.封裝得到鼠標當前位置的系統。

3.完成拖拽的實現。

首先,我們要講到鼠標位置的獲取,講到這個,就離不開js的window.event事件了。先展開一個例子:

 <div id="drag"></div>
 *{margin: 0;padding: 0}
        #drag{
            position: absolute;
            top: 100px;
            left: 200px;
            width: 60px;height: 60px;
            background-color: red;
        }

當我點擊紅色div的中間偏上的地方,打印他的event對象,看到里面給了好多屬性,我們來一一解釋一下。先盜一個表:

名稱 解釋
clientX 事件屬性返回當事件被觸發時鼠標指針向對於瀏覽器頁面(或客戶區)的水平坐標。
clientY 事件屬性返回當事件被觸發時鼠標指針向對於瀏覽器頁面(客戶區)的垂直坐標。
screenX 事件屬性可返回事件發生時鼠標指針相對於屏幕的水平坐標。
screenY 事件屬性可返回事件發生時鼠標指針相對於屏幕的垂直坐標。
offsetX 事件發生的地點在事件源元素的坐標系統中的 x 坐標(ie)。
offsetY 事件發生的地點在事件源元素的坐標系統中的 y 坐標(ie)。
x 事件發生的位置的 x 坐標, 它相對於用CSS動態定位的最內層包容元素(ie,~pageX)。
y 事件發生的位置的 y 坐標, 它相對於用CSS動態定位的最內層包容元素(ie,~pageY)。
pageX 鼠標指針的位置,相對於文檔的左邊緣(firefox,~x)。
pageY 鼠標指針的位置,相對於文檔的上邊緣(firefox,~y)。
layerX 鼠標相比較於當前坐標系的位置(firefox,~offsetX)。
layerY 鼠標相比較於當前坐標系的位置(firefox,~offsetY)。

 

 

 

 

 

 

 

 

 

 

 

 

然后把剛剛的圖截完:

我這個div的寬60,高60,left:200,top:100;

clientX/Y:可以看到它的clientX是229,根據表里的描述,它是鼠標指針到瀏覽器頁面,不包含瀏覽器的工具欄什么的。因為我點的大約是div的中部最上面,所以它的值就等於top值:100px。X的229就是200的left加上了一半的寬30---就是230左右。(由於我隨便點的,不准確,但是基本接近)。

screenX/Y:相對於屏幕的,可以看到X沒怎么變,Y變成了163。就是因為它有61px的工具欄和導航欄的高度。so,你把瀏覽器縮小,它還是相對於屏幕,而不是瀏覽器,你會發現它就和上一個差太多了。

offsetX/Y:這個就比較有用了,鼠標相對於這個元素的位置,offset嘛,就是相對了。可以看到x是29,y是2,因為我大約點的中間。

x/y: 相對於它父元素的位置,相當於firefox中的pageX、pageY坐標。當父元素是document的時候就跟clientX/Y一樣。因為它的父元素就是document。。。所以跟上面那幾個一樣。說是ie特有,不過我chrome上面也有這個屬性。但是我chrome的x,y的屬性就算你有父元素還是等於clientX/Y,高版本ie也是如此。大家就把它記作clientX/Y就好。

layerX/Y:其實就是offsetX/Y,不過offsetX/Y是ie的屬性,layerX/Y是firefox支持的。chrome我這個版本都支持了。

pageX/Y:鼠標指針的位置,相對於文檔的左邊緣和上邊緣,是firefox中支持的,相似於ie中的x和y。和client區別就是如果有滾動條,他是大於client的

總結一下:clientX/Y== X/Y==無滾動條下pageX/Y    offsetX/Y==layerX/Y  screenX/Y相對於屏幕,就它自己。

那回到我們取鼠標坐標,怎么辦呢,看能用到哪個屬性:clientX/Y這就是鼠標真正的坐標,相對於本頁面的坐標。然后offsetX/Y是相對於div的偏移。那么這個div的位置就是pageX/Y-offsetX/Y;大家打印一下,就能知道x總是返回100,y返回200;

那我們開始寫取坐標的位置的兼容js:

function getPosition(e){
     e=e||window.event;
    var target=e.target?e.target:e.srcElement;  //兼容ie的srcElement
   
    var pos_rel={};
    var pos_offset={};
    pos_rel={
        x:e.pageX?e.pageX:e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft),//clientX加上滾動條滾動的位置
        y:e.pageY?e.pageY:e.clientY+(document.body.scrollTop||document.documentElement.scrollTop)
    }
    pos_offset={
        x:e.offsetX?e.offsetX:e.layerX,
        x:e.offsetY?e.offsetY:e.layerY
    }
   return {
         rel:pos_rel,
         offset:pos_offset
   }
}

 

取到這個位置就好做拖拽了。就是讓鼠標點擊的時候記錄相對於div的x,y,鼠標移動設置div的left和top,記得減去剛剛記錄的offsetX/Y。鼠標松開就設置不能移動。

好,在這之前先說一下封裝事件系統

 事件系統就是為了ie不支持addEventListener才做的封裝兼容

別的瀏覽器可以addEventListener和removeEventListener,而ie的是attachEvent和detachEvent。ie的這個和addEventListener用法是相似的,需要注意的一點就是要把處理事件保存用以解除監聽。

我上一下我寫的事件封裝:

var addEvent=function(el,event,cb){
  if (el.addEventListener) {
        el.addEventListener(event,cb);
  }else if(el.attachEvent){
      el.attachEvent(event,cb);
  }
  return cb; //注意這里返回處理函數
}
var cancelEvent=function(el,event,cb){
   if (el.removeEventListener) {
          el.removeEventListener(event,cb);
   }else if(el.detachEvent){
           el.detachEvent('on'+event,cb)
   }
} 

使用就是

var handle=addEvent(document,"click",function(e){
    console.log("be clicked")
})

解除事件監聽:

cancelEvent(document,"click",handle)

這里我沒有寫第三個參數,默認冒泡添加解除事件,有需要也可以多加參數。

好,那么開始寫拖拽吧:

首先點擊這個div記錄當前offsetX,Y

var isDrag=false;var ofx,ofy;
var mousedownH=addEvent(drag,"mousedown",function(e){
    isDrag=true;
    ofx=getPosition().offset.x;
    ofy=getPosition().offset.y;
})

 

然后設置div位置:

var mousemoveH=addEvent(document,"mousemove",function(e){  //注意這里的mousemove和mouseup都是在document上的事件,這是為了避免你鼠標移動太快,移出了這個div,就沒有move事件觸發了。
     if(isDrag) {
       var relX=getPosition().rel.x-ofx;
       var relY=getPosition().rel.y-ofx;
       drag.style.left=relX+"px";
       drag.style.top=relY+"px";
   };
})

 

最后鼠標抬起取消它的可移動:

var mouseupH=addEvent(document,"mouseup",function(e){
    isDrag=false;
})

 

搞定。

最后把全部代碼分享,大家復制就可以用了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>js拖拽</title>
    <style type="text/css">
        *{margin: 0;padding: 0}
        #drag{
            position: absolute;
            top: 100px;
            left:200px;
            width: 60px;height: 60px;
            background-color: red;
        }
    </style>
</head>
<body>
    <div id="drag"></div>
</body>
<script type="text/javascript">
var drag=document.getElementById('drag');
var click1=document.getElementById('click');
var can=document.getElementById('can');
var addEvent=function(el,event,cb){
  if (el.addEventListener) {
        el.addEventListener(event,cb);
  }else if(el.attachEvent){
      el.attachEvent(event,cb);
  }
  return cb;
}
var cancelEvent=function(el,event,cb){
   if (el.removeEventListener) {
          el.removeEventListener(event,cb);
   }else if(el.detachEvent){
           el.detachEvent('on'+event,cb)
   }
}                         
function getPosition(e){
     e=e||window.event;
    var target=e.target?e.target:e.srcElement;
   
    var pos_rel={};
    var pos_offset={};
    pos_rel={
        x:e.pageX?e.pageX:e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft),
        y:e.pageY?e.pageY:e.clientY+(document.body.scrollTop||document.documentElement.scrollTop)
    }
    pos_offset={
        x:e.offsetX?e.offsetX:e.layerX,
        x:e.offsetY?e.offsetY:e.layerY
    }
   return {
         rel:pos_rel,
         offset:pos_offset
   }
}
var isDrag=false;var ofx,ofy;
var mousedownH=addEvent(drag,"mousedown",function(e){
    isDrag=true;
    ofx=getPosition().offset.x;
    ofy=getPosition().offset.y;
})
var mousemoveH=addEvent(document,"mousemove",function(e){
     if(isDrag) {
       var relX=getPosition().rel.x-ofx;
       var relY=getPosition().rel.y-ofx;
       drag.style.left=relX+"px";
       drag.style.top=relY+"px";
   };
})
var mouseupH=addEvent(document,"mouseup",function(e){
    isDrag=false;
})
</script>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM