JS基本功系列-鼠标事件深入

admin 2022年5月12日23:34:30安全开发评论5 views13128字阅读43分45秒阅读模式

前置知识

鼠标点击
鼠标右键、中键没有onclick事件,有onmouseup事件
e.button 左中右分别对应012
IE10以上使用,否则就不要去添加这些事件了
鼠标右键事件contextmenu  
模拟双击事件,两次点击的时间间隔 < 200ms  

点击事件 = mousedown + mouseup  
position: absolute 会将内联元素变为块级(比如a)
a标签的协议限定符(伪协议,防止跳转和刷新,让href不生效),javascript:;,可以让点击和拖拽分离
模块的声明:xx变量 = function () { } / IIFE  
等待型模块和立即执行的模块  
用按下、抬起的时间差值来判断是拖拽还是点击  

模块拖动案例

需求: 点击的时候跳转
拖动鼠标抬起的时候不跳转
鼠标拖动并跳转链接的时候回到原位

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<style>
  body {
    margin0;
  }

  a {
    position: absolute;
    top0;
    left0;
    width100px;
    height100px;
    background-color: green;
  }

  div {
    display: none;
    position: absolute;
    top0;
    left0;
    width100px;
    height100px;
    background-color: orange;
  }
</style>
<body>
<a href="javascript:;"></a>
<div></div>

<script type="text/javascript" src="./utils.js"></script>
<script type="text/javascript">
  // 点击的时候跳转
  // 拖动鼠标抬起的时候不跳转
  // 鼠标拖动并跳转链接的时候回到原位
  var dragNclcik = (function (elem, elemclick{

    var bTime = 0// 记录点击时间
      eTime = 0,
      oPos = []; // 记录原先位置

    drag();

    function drag({
      var x,
        y;

      addEvent(elem, 'mousedown'function (e{
        var e = e || window.event;
        bTime = new Date().getTime();
        oPos = [getStyles(elem, 'left'), getStyles(elem, 'top')]
        x = pagePos(e).X - getStyles(elem, 'left');
        y = pagePos(e).Y - getStyles(elem, 'top');

        addEvent(document'mousemove', mouseMove);
        addEvent(document'mouseup', mouseUp);
        cancelBubble(e);
        stopEvent(e);
      })

      function mouseMove(e{
        var e = e || window.event;

        elem.style.top = pagePos(e).Y - y + 'px';
        elem.style.left = pagePos(e).X - x + 'px';
      }

      function mouseUp(e{
        var e = e || window.event;
        eTime = new Date().getTime();

        console.log(eTime - bTime);
        console.log(oPos[0]);


        if (eTime - bTime < 100) {
          elem.style.left = oPos[0] + 'px';
          elem.style.top = oPos[1] + 'px';
          elemclick();
        }
        removeEvent(document'mousemove', mouseMove);
        removeEvent(document'mouseup', mouseUp);
      }
    }
  })
  var oLink = document.getElementsByTagName('a')[0];
  dragNclcik(oLink, function ({
    window.open('http://www.baidu.com');
  });


  //写到原型上面
  Element.prototype.dragNclcik = (function (elemclick{

    var bTime = 0// 记录点击时间
      eTime = 0,
      oPos = []; // 记录原先位置

    drag.call(this);

    function drag({
      var x,
        y,
        _self = this;

      addEvent(_self, 'mousedown'function (e{
        var e = e || window.event;
        bTime = new Date().getTime();
        oPos = [getStyles(_self, 'left'), getStyles(_self, 'top')]
        x = pagePos(e).X - getStyles(_self, 'left');
        y = pagePos(e).Y - getStyles(_self, 'top');

        addEvent(document'mousemove', mouseMove);
        addEvent(document'mouseup', mouseUp);
        cancleBubble(e);
        preventDefaultEvent(e);
      })

      function mouseMove(e{
        var e = e || window.event;

        _self.style.top = pagePos(e).Y - y + 'px';
        _self.style.left = pagePos(e).X - x + 'px';
      }

      function mouseUp(e{
        var e = e || window.event;
        eTime = new Date().getTime();

        console.log(eTime - bTime);
        console.log(oPos[0]);


        if (eTime - bTime < 100) {
          _self.style.left = oPos[0] + 'px';
          _self.style.top = oPos[1] + 'px';
          elemclick();
        }
        removeEvent(document'mousemove', mouseMove);
        removeEvent(document'mouseup', mouseUp);
      }
    }
  })

  // //调用
  // var oLink = document.getElementsByTagName('a')[0];
  // oLink.dragNclcik(function () {
  //   window.open('http://www.baidu.com');
  // });

</script>


</body>
</html>

解决模块边界问题

 Element.prototype.dragNclcik = (function (elemclick{

    var bTime = 0// 记录点击时间
      eTime = 0,
      oPos = [], // 记录原先位置
      wWidth = getViewportSize().width,
      wHeight = getViewportSize().height,
      elemWidth = getStyles(this'width'),
      elemHeight = getStyles(this'height');

    drag.call(this);

    function drag({
      var x,
        y,
        _self = this;

      addEvent(_self, 'mousedown'function (e{
        var e = e || window.event;
        bTime = new Date().getTime();
        oPos = [getStyles(_self, 'left'), getStyles(_self, 'top')]
        x = pagePos(e).X - getStyles(_self, 'left');
        y = pagePos(e).Y - getStyles(_self, 'top');

        addEvent(document'mousemove', mouseMove);
        addEvent(document'mouseup', mouseUp);
        cancleBubble(e);
        preventDefaultEvent(e);
      })

      function mouseMove(e{
        var e = e || window.event,
          elemLeft = pagePos(e).X - x,
          elemTop = pagePos(e).Y - y;

        if (elemLeft <= 0) {
          elemLeft = 0;
        } else if (elemLeft >= wWidth - elemWidth) {
          elemLeft = wWidth - elemWidth - 1;  // 避免误差
        }

        if (elemTop <= 0) {
          elemTop = 0;
        } else if (elemTop >= wHeight - elemHeight) {
          elemTop = wHeight - elemHeight - 1;
        }

        _self.style.top = elemTop + 'px';
        _self.style.left = elemLeft + 'px';
      }

      function mouseUp(e{
        var e = e || window.event;
        eTime = new Date().getTime();

        console.log(eTime - bTime);
        console.log(oPos[0]);


        if (eTime - bTime < 100) {
          _self.style.left = oPos[0] + 'px';
          _self.style.top = oPos[1] + 'px';
          elemclick();
        }
        removeEvent(document'mousemove', mouseMove);
        removeEvent(document'mouseup', mouseUp);
      }
    }
  })


  var oLink = document.getElementsByTagName('a')[0];
  oLink.dragNclcik(function ({
    window.open('http://www.baidu.com');
  });

解决右击菜单边界问题

JS基本功系列-鼠标事件深入

  Element.prototype.dragNclcik = (function (menu, elemclick{

    var bTime = 0// 记录点击时间
      eTime = 0,
      oPos = [], // 记录原先位置
      wWidth = getViewportSize().width,
      wHeight = getViewportSize().height,
      elemWidth = getStyles(this'width'),
      elemHeight = getStyles(this'height'),
      mWidth = getStyles(menu, 'width'),
      mHeight = getStyles(menu, 'height');

    drag.call(this);

    function drag({
      var x,
        y,
        _self = this;

      addEvent(_self, 'mousedown'function (e{
        var e = e || window.event,
          btnCode = e.button;
        if (btnCode === 2) {
          var mLeft = pagePos(e).X,
            mTop = pagePos(e).Y;

          if (mLeft <= 0) {
            mLeft = 0;
          } else if (mLeft >= wWidth - mWidth) {
            mLeft = pagePos(e).X - mWidth;//详细解释见上图
          }

          if (mTop <= 0) {
            mTop = 0;
          } else if (mTop >= wHeight - mHeight) {
            mTop = pagePos(e).Y - mHeight;
          }

          menu.style.left = mLeft + 'px';
          menu.style.top = mTop + 'px';
          menu.style.display = 'block';

        } else if (btnCode === 0) {
          bTime = new Date().getTime();
          oPos = [getStyles(_self, 'left'), getStyles(_self, 'top')]
          menu.style.display = 'none';

          x = pagePos(e).X - getStyles(_self, 'left');
          y = pagePos(e).Y - getStyles(_self, 'top');

          addEvent(document'mousemove', mouseMove);
          addEvent(document'mouseup', mouseUp);
          cancleBubble(e);
          preventDefaultEvent(e);
        }

      })

      addEvent(document'contextmenu'function (e{
        var e = e || window.event;
        preventDefaultEvent(e);
      })

      addEvent(document'click'function (e{
        menu.style.display = 'none';
      })

      addEvent(menu, 'click'function (e{
        cancleBubble(e)
      })

      function mouseMove(e{
        var e = e || window.event,
          elemLeft = pagePos(e).X - x,
          elemTop = pagePos(e).Y - y;

        if (elemLeft <= 0) {
          elemLeft = 0;
        } else if (elemLeft >= wWidth - elemWidth) {
          elemLeft = wWidth - elemWidth - 1;  // 避免误差
        }

        if (elemTop <= 0) {
          elemTop = 0;
        } else if (elemTop >= wHeight - elemHeight) {
          elemTop = wHeight - elemHeight - 1;
        }

        _self.style.top = elemTop + 'px';
        _self.style.left = elemLeft + 'px';
      }

      function mouseUp(e{
        var e = e || window.event;
        eTime = new Date().getTime();

        console.log(eTime - bTime);
        console.log(oPos[0]);


        if (eTime - bTime < 100) {
          _self.style.left = oPos[0] + 'px';
          _self.style.top = oPos[1] + 'px';
          elemclick();
        }
        removeEvent(document'mousemove', mouseMove);
        removeEvent(document'mouseup', mouseUp);
      }
    }
  })

  var oLink = document.getElementsByTagName('a')[0],
    oMenu = document.getElementsByTagName('div')[0];
  oLink.dragNclcik(oMenu, function ({
    window.open('http://www.baidu.com');
  });

双击事件

 Element.prototype.dragNclcik = (function (menu, elemclick{

    var bTime = 0// 记录点击时间
      eTime = 0,
      oPos = [], // 记录原先位置
      cbTime = 0,
      ceTime = 0,
      counter = 0,
      t = null,
      wWidth = getViewportSize().width,
      wHeight = getViewportSize().height,
      elemWidth = getStyles(this'width'),
      elemHeight = getStyles(this'height'),
      mWidth = getStyles(menu, 'width'),
      mHeight = getStyles(menu, 'height');

    drag.call(this);

    function drag({
      var x,
        y,
        _self = this;

      addEvent(_self, 'mousedown'function (e{
        var e = e || window.event,
          btnCode = e.button;
        if (btnCode === 2) {
          var mLeft = pagePos(e).X,
            mTop = pagePos(e).Y;

          if (mLeft <= 0) {
            mLeft = 0;
          } else if (mLeft >= wWidth - mWidth) {
            mLeft = pagePos(e).X - mWidth;
          }

          if (mTop <= 0) {
            mTop = 0;
          } else if (mTop >= wHeight - mHeight) {
            mTop = pagePos(e).Y - mHeight;
          }

          menu.style.left = mLeft + 'px';
          menu.style.top = mTop + 'px';
          menu.style.display = 'block';

        } else if (btnCode === 0) {
          bTime = new Date().getTime();
          oPos = [getStyles(_self, 'left'), getStyles(_self, 'top')]
          menu.style.display = 'none';

          x = pagePos(e).X - getStyles(_self, 'left');
          y = pagePos(e).Y - getStyles(_self, 'top');

          addEvent(document'mousemove', mouseMove);
          addEvent(document'mouseup', mouseUp);
          cancleBubble(e);
          preventDefaultEvent(e);
        }

      })

      addEvent(document'contextmenu'function (e{
        var e = e || window.event;
        preventDefaultEvent(e);
      })

      addEvent(document'click'function (e{
        menu.style.display = 'none';
      })

      addEvent(menu, 'click'function (e{
        cancleBubble(e)
      })

      function mouseMove(e{
        var e = e || window.event,
          elemLeft = pagePos(e).X - x,
          elemTop = pagePos(e).Y - y;

        if (elemLeft <= 0) {
          elemLeft = 0;
        } else if (elemLeft >= wWidth - elemWidth) {
          elemLeft = wWidth - elemWidth - 1;  // 避免误差
          //浏览器可能有计算误差,可以适当将范围缩小1像素,防止出现滚动条
        }

        if (elemTop <= 0) {
          elemTop = 0;
        } else if (elemTop >= wHeight - elemHeight) {
          elemTop = wHeight - elemHeight - 1;
          //浏览器可能有计算误差,可以适当将范围缩小1像素,防止出现滚动条
        }

        _self.style.top = elemTop + 'px';
        _self.style.left = elemLeft + 'px';
      }

      function mouseUp(e{
        var e = e || window.event;
        eTime = new Date().getTime();

        if (eTime - bTime < 200) {
          _self.style.left = oPos[0] + 'px';
          _self.style.top = oPos[1] + 'px';

          counter++;

          if (counter === 1) {
            cbTime = new Date().getTime();
          }

          if (counter === 2) {
            ceTime = new Date().getTime();
          }

          if (cbTime && ceTime && (ceTime - cbTime < 200)) {
            console.log(ceTime - cbTime, counter);
            elemclick();
          }

          t = setTimeout(function ({
            cbTime = 0;
            ceTime = 0;
            counter = 0;
            clearTimeout(t)
          }, 500);

        }

        removeEvent(document'mousemove', mouseMove);
        removeEvent(document'mouseup', mouseUp);
      }
    }
  })



  var oLink = document.getElementsByTagName('a')[0],
    oMenu = document.getElementsByTagName('div')[0];
  oLink.dragNclcik(oMenu, function ({
    window.open('http://www.baidu.com');
  });



(1)为什么要清除计时器?因为计时器是保存在内存里面的,不用了把它清除是一种好习惯

(2)为什么要清零

cbTime = 0;
ceTime = 0;
counter = 0;

因为你点击第一次的时候会保存cbTime

第二次点击会保存ceTime

但是如果ceTime - cbTime ≮ 200的话,cbTime、ceTime、counter就不会清零,也不会执行函数

往后点counter就会从2一直往后加,往后加就不会重新获取时间戳,然后cbTime、ceTime一直都是固定的,而且ceTime - cbTime ≮ 200,就一直进入不到if语句里面

所以要进行清零,因为当ceTime - cbTime ≮ 200的时候,就可以重新获取时间戳,然后计算它们的差值

(3)为什么要用延时器清零?

t = setTimeout(function ({
    cbTime = 0;
    ceTime = 0;
    counter = 0;
    clearTimeout(t)
}, 500);

因为当你只点击了一次的时候,它没有清除,然后下一次双击的时候就会出现问题,因为counter是从第一次点击时开始计算的,就是从1开始加,加到2、3,当你第二次进行双击的时候ceTime - cbTime 肯定就大于 200毫妙了,然后就进入不到if语句,只要counter不清零,就永远不会重新获取时间戳,不重新获取时间戳就无法重新计算ceTime - cbTime,就进入不到语句。

所以设置延时器清零,就是为当你只点击了1次的情况,它会延迟500毫妙自动给你清零,然后你下一次双击的时候,就可以重新获取时间戳,重新计算ceTime - cbTime,从而进入语句。

utils.js代码地址

https://github.com/richard1230/CodeLearning/blob/main/Javascript/JavaScript%E5%9F%BA%E6%9C%AC%E5%8A%9F/DOM/dom/utils.js


原文始发于微信公众号(迪哥讲事):JS基本功系列-鼠标事件深入

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月12日23:34:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  JS基本功系列-鼠标事件深入 http://cn-sec.com/archives/997863.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: