拖拽的原理

这个问题之前在面试的时候有遇到过,现在整理一下,这样也能更好的理解事件流。
拖拽的原理:
(1)鼠标和div的相对距离不变
(2)三大事件:onmousedown(选择元素) -> onmousemove(移动元素) -> onmouseup(释放元素)
(3)把拖拽加到document

#div1{
        width: 100px;
        height: 100px;
        position: absolute;
        background-color: red;
    }
<div id="div1"></div>
var oDiv = document.getElementById('div1'); 

oDiv.onmousedown = function(ev){
    var ev = ev || event;
    var disX = ev.clientX - this.offsetLeft;
    var disY = ev.clientY - this.offsetTop;

    document.onmousemove = function(ev){ //不是oDiv.onmousemove的原因是防止拖快的话鼠标脱离div,div就不跟随
        var ev = ev || event;

        oDiv.style.left = ev.clientX - disX + 'px';
        oDiv.style.top = ev.clientY - disY + 'px';

    }

    document.onmouseup = function(){
        document.onmousemove = document.onmouseup = null; //释放 不是oDiv.onmouseup和oDiv.onmousemove的原因是为了防止当div被遮盖时释放鼠标(onmouseup)无效(因为释放鼠标是触发遮盖的那层的)
    }
}

拖拽的问题以及解决办法:
(1)拖拽的时候,如果有文字被选中,会产生问题。
原因:当鼠标按下的时候,如果页面中有文字被选中,会触发浏览器的默认拖拽文字的效果。
解决方法:
标准下:在onmousedown事件的函数里面添加return false;
非标准IE下:通过在ie下设置全局捕获,用setCapture()方法曲线救国
(2)拖拽图片会有问题,原因和解决方法同

全局捕获:
方法:元素.setCapture();
当我们给一个元素设置全局捕获以后,这个元素就会监听后续发生的所有事件,当有事件发生的时候,就会被当前设置了全局捕获的元素所触发
兼容性问题:
IE:有,并且有效果
ff:有,但是没效果
chrome:没有这个方法
与之对应的释放全局捕获的方法是:元素.releaseCapture();

修改后的代码

var oDiv = document.getElementById('div1');
 oDiv.onmousedown = function(ev) {
  var ev = ev || event;
  var disX = ev.clientX - this.offsetLeft;
  var disY = ev.clientY - this.offsetTop;
  if ( oDiv.setCapture ) {
   oDiv.setCapture();
  } //兼容代码
  document.onmousemove = function(ev) {
   var ev = ev || event;
   oDiv.style.left = ev.clientX - disX + 'px';
   oDiv.style.top = ev.clientY - disY + 'px';
  }

  document.onmouseup = function() {
   document.onmousemove = document.onmouseup = null;
   //释放全局捕获 releaseCapture();
   if ( oDiv.releaseCapture ) {
    oDiv.releaseCapture();
   } //兼容代码
  }
  return false; //阻止浏览器的默认行为
 }

拖拽函数封装

function drag(obj) {
  obj.onmousedown = function(ev) {
   var ev = ev || event;
   var disX = ev.clientX - this.offsetLeft;
   var disY = ev.clientY - this.offsetTop;
   if ( obj.setCapture ) {
    obj.setCapture();
   }
   document.onmousemove = function(ev) {
    var ev = ev || event;
    obj.style.left = ev.clientX - disX + 'px';
    obj.style.top = ev.clientY - disY + 'px';
   }
   document.onmouseup = function() {
    document.onmousemove = document.onmouseup = null;
    //释放全局捕获 releaseCapture();
    if ( obj.releaseCapture ) {
     obj.releaseCapture();
    }
   }
   return false;
  }
 }

限制范围的拖拽

function drag(obj){
    obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft;
        var disY = ev.clientY - this.offsetTop;
        if(obj.setCapture){
            obj.setCapture();
        }
        document.onmousemove = function(ev){
            var ev = ev || event;
            var L = ev.clientX - disX;
            var T = ev.clientY - disY;
            // 限制拖拽范围在页面内
            if(L < 0){
                L = 0;
            } else if( L > document.documentElement.clientWidth - obj.offsetWidth){
                L = document.documentElement.clientWidth - obj.offsetWidth;
            }
            if(T < 0){
                T = 0;
            } else if(T > document.documentElement.clientHeight - obj.offsetHeight){
                T = document.documentElement.clientHeight - obj.offsetHeight;
            }
            obj.style.left = L + 'px';
            obj.style.top = T  + 'px';
        }
        document.onmouseup = function(){
            document.onmousemove = document.onmouseup = null;
            if(obj.releaseCapture){
                obj.releaseCapture();
            }
        }
        return false;
    }  
}

磁性吸附

function drag(obj){
    obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft;
        var disY = ev.clientY - this.offsetTop;

        if(obj.setCapture){
            obj.setCapture();
        }

        document.onmousemove = function(ev){
            var ev = ev || event;
            var L = ev.clientX - disX;
            var T = ev.clientY - disY;

            // 限制拖拽范围在页面内
            if(L < 100){ //只要把原来的0改为一个范围,例如:100,就实现了磁性吸附的效果
                L = 0;
            } else if( L > document.documentElement.clientWidth - obj.offsetWidth){
                L = document.documentElement.clientWidth - obj.offsetWidth;
            } //如果想让右边吸附的话将条件L > document.documentElement.clientWidth -                     obj.offsetWidth-100
            if(T < 100){
                T = 0;
            } else if(T > document.documentElement.clientHeight - obj.offsetHeight){
                T = document.documentElement.clientHeight - obj.offsetHeight;
            }

            obj.style.left = L + 'px';
            obj.style.top = T  + 'px';

        }

        document.onmouseup = function(){
            document.onmousemove = document.onmouseup = null;

            if(obj.releaseCapture){
                obj.releaseCapture();
            }
        }

        return false;
    }  
}

碰撞检测

#div1{
        width: 100px;
        height: 100px;
        position: absolute;
        background-color: red;
    }
    #img1{
        position: absolute;
        left: 500px;
        top:200px;
    }
<div id="div1"></div>
<img id="img1" src="1.jpg" >
var oDiv = document.getElementById('div1');
 var oImg = document.getElementById('img1');
 drag(oDiv);
 function drag(obj) {
  obj.onmousedown = function(ev) {
   var ev = ev || event;
   var disX = ev.clientX - this.offsetLeft;
   var disY = ev.clientY - this.offsetTop;
   if ( obj.setCapture ) {
    obj.setCapture();
   }
   document.onmousemove = function(ev) {
    var ev = ev || event;
    var L = ev.clientX - disX;
    var T = ev.clientY - disY;

    //被拖动的元素的四条边
    var L1 = L;  //左边的left值
    var R1 = L + obj.offsetWidth; //右边的left值
    var T1 = T; //上边的top值
    var B1 = T + obj.offsetHeight;//底边的top值

//被碰撞的元素的四条边(这个例子里面是img元素)
    var L2 = oImg.offsetLeft;
    var R2 = L2 + oImg.offsetWidth;
    var T2 = oImg.offsetTop;
    var B2 = T2 + oImg.offsetHeight;

    if ( R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2 ) {
     oImg.src = '1.jpg';
    } else {
     oImg.src = '2.jpg';
    }

    obj.style.left = L + 'px';
    obj.style.top = T + 'px';

   }

   document.onmouseup = function() {
    document.onmousemove = document.onmouseup = null;
    if ( obj.releaseCapture ) {
     obj.releaseCapture();
    }
   }

   return false;

  }

 }

拖拽改变层大小

var oDiv = document.getElementById('div1');

    document.onmousemove = function(ev) {
     moveDef(oDiv);
    }
 function moveDef(obj){
  var ev = ev || event;
  var disX = ev.clientX;
  var disY = ev.clientY;
  var disW = obj.offsetWidth;
  var disL = obj.offsetLeft;
  var disH = obj.offsetHeight;
  var disT = obj.offsetTop;
  if( disL - 5 < disX && disX < disL + 5 || disW + disL-5 < disX && disX< disW + disL + 5){
   obj.style.cursor = 'w-resize';
  }else if(disT - 5 < disY && disY < disT + 5 || disH + disT-5 < disY && disY< disH + disT + 5){
   obj.style.cursor = 's-resize';
  }else{
   obj.style.cursor = 'default';
  }
 }

 oDiv.onmousedown = function(ev) {

  var _this = this;
  var ev = ev || event;
  var disX = ev.clientX;
  var disY = ev.clientY;
  var disW = this.offsetWidth;
  var disL = this.offsetLeft;
  var disH = this.offsetHeight;
  var disT = this.offsetTop;

  var b = '';

  if ( disX > disL + disW - 5 ) {
   b = 'right';
  }
  if ( disX < disL + 5 ) {
   b = 'left';
  }
  if ( disY > disT + disH - 5 ) {
   b = 'bootom';
  }
  if ( disY < disT + 5 ) {
   b = 'top';
  }

  document.onmousemove = function(ev) {

   var ev = ev || event;

   switch( b ) {

    case 'left':
     oDiv.style.width = disW - ( ev.clientX - disX ) + 'px';
     oDiv.style.left = disL + ( ev.clientX - disX ) + 'px';
     break;

    case 'right':
     oDiv.style.width = disW + ( ev.clientX - disX ) + 'px';
     break;
    case 'top':
     oDiv.style.height = disH - ( ev.clientY - disY ) + 'px';
     oDiv.style.top = disT + ( ev.clientY - disY ) + 'px';
     break;

    case 'bootom':
     oDiv.style.height = disH + ( ev.clientY - disY ) + 'px';
     break;

   }

  }

  document.onmouseup = function() {
   document.onmousemove = function(ev) {
        moveDef(oDiv);
      };
      document.onmouseup = null;
   _this.style.cursor = 'default';
  }

  return false;

 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值