• 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;
                 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>
  • 相关阅读:
    LeetCode :: Validate Binary Search Tree[具体分析]
    一世12年龄在泥土还在打,硅谷00创业毕竟开始播放!
    大学毕业生上班第一天6月3号码
    发送到快捷方式不见了
    【转】三种方式在C++中调用matlab
    【转】C++调用Matlab的.m文件
    C++函数模板与模板函数
    Visual Studio 行末回车时运算符两侧自动加空格是怎么设置的
    java回顾4 Java基本数据类型
    zoj 2402
  • 原文地址:https://www.cnblogs.com/dh-dh/p/5310807.html
Copyright © 2020-2023  润新知