基本拖拽和拖拽衍生的问题

1、拖拽的原理

主要是用了三个鼠标事件,onmousedown、onmousemove、onmouseup。当鼠标按下时,计算出鼠标距离拖拽物体border的距离,假设拖拽物体是一个100*100px的小块,在鼠标按下时再检测鼠标移动后鼠标的位置,用当前鼠标的位置去减去鼠标距离拖拽物体border的距离,把作差的结果赋给div的left和top,这样就达到拖拽的目的,当然当鼠标释放时,还是把onmousemove、onmousedown事件清除,已达到拖拽完鼠标释放的目的。这就是简单的拖拽原理。也是最实用的。

下面是源码:

  <!DOCTYPE html>
  <html>
  <head lang="en">
      <meta charset="UTF-8">
      <title></title>
  </head>
  <style>
      #div1{100px;  height: 100px;  background-color: red; position: absolute}
  </style>
 <script>
     window.onload=function(){
         var oDiv=document.getElementById(id);
         oDiv.onmousedown=function(ev){
             oEvent=ev||event;
             //鼠标距离小块border的距离
             var disX=oEvent.clientX-oDiv.offsetLeft;
             var disY=oEvent.clientY-oDiv.offsetTop;
             document.onmousemove=function(ev){
                 oEvent=ev||event;
                 //移动后,想要移动的距离
                 var l=oEvent.clientX-disX;
                 var t=oEvent.clientY-disY;
                 //把l和t赋值给div的left和top让其达到运动的效果
                 oDiv.style.left=l+'px';
                 oDiv.style.top=t+'px';
             };
             document.onmouseup=function(){
                 //鼠标释放后,把事件清空
                 document.onmousedown=null;
                 document.onmousemove=null
            }
         }
     }
 </script>
 <body>
 <div id="div1"></div>
</body>
</html>
为什么要把onmousemove事件加到onmousedown事件里面?  防止抖动
为什么要document.onmousemove  因为document足够大

在这里不得不说下,style.width/height和offsetLeft/Top的区别,下面是以width举例的,height也类似

offsetWidth属性可以返回对象的padding+border+width属性值之和
offsetWidth属性仅是可读属性,而style.width是可读写的。
offsetWidth属性返回值是整数,而style.width的返回值是字符串。
style.width仅能返回以行内方式定义的内部样式表的width属性值
2、有限制范围的拖拽
其实有限制范围的拖拽很简单,就是判断l和t的取值范围
代码如下:
                 if(l<0)
                {
                    l=0;
                }
                else if(l>document.documentElement.clientWidth-oDiv.offsetWidth)
                {
                    l=document.documentElement.clientWidth-oDiv.offsetWidth;
                }
                if(t<){
                    t=0;
                }
                else if(t>document.documentElement.clientHeight-oDiv.offsetHeight){
                    t=document.documentElement.clientHeight-oDiv.offsetHeight
                }            

document.documentElement.clientWidth就是当前网页窗口的宽度,如果调整了网页宽口的宽度,document.documentElement.clientWidth也会根据你调整后变化。

document.documentElement.clientHeight也类似

下面附一张图来解释原理

left和top容易理解,right和bottom是这样的,上图 a=offsetLeft b=document.documentElement.clientWidth c=小块宽度,当a>b-c时说明小块出去了,这时候把l=document.documentElement.clientWidth-oDiv.offsetWidth。height同理,这样就达到了不让小块出界的目的

3、磁性吸附

磁性吸附就是小块快到上下左右边界时,让小块立马贴近边界,达到吸附的目的

代码如下:

   if(l<50)
                {
                    l=0;
                }
                else if(l>document.documentElement.clientWidth-oDiv.offsetWidth-50)
                {
                    l=document.documentElement.clientWidth-oDiv.offsetWidth;
                }
                if(t<50){
                    t=0;
                }
                else if(t>document.documentElement.clientHeight-oDiv.offsetHeight-50){
                    t=document.documentElement.clientHeight-oDiv.offsetHeight
                }

磁性吸附其实和限制小块范围的原理类似,当l还有50px小于0,这时候把l等于0,以至于在l<50范围内,都让l=0; 当l>document.documentElement.clientWidth-oDiv.offsetWidth-50时,l=document.documentElement.clientWidth-oDiv.offsetWidth让小块立即贴近页面右边框。

如上图,当小块向右距离小于50px 都是l>document.documentElement.clientWidth-oDiv.offsetWidth-50,把其l=document.documentElement.clientWidth-oDiv.offsetWidth,这样就达成了磁性吸附的目的。

4、碰撞检测
碰撞检测的原理很简单,有两个div,div1和div2,在div1可以移动 div2保持不动,div1在div2大小之外,就让其颜色不变,当在div2内,让其颜色改变。

代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
    #div1{width:100px;  height: 100px;  background-color: red; position: absolute;z-index:2;}
    #div2{width:100px;  height: 100px;  background-color: green; position: absolute ;left:300px;top:500px;z-index: 1}
</style>
<script>
    window.onload=function(){
        var oDiv=document.getElementById('div1');
        var oDiv2=document.getElementById('div2');
        oDiv.onmousedown=function(ev){
            oEvent=ev||event;
            //移动前的距离window的距离
            var disX=oEvent.clientX-oDiv.offsetLeft;
            var disY=oEvent.clientY-oDiv.offsetTop;
            document.onmousemove=function(ev){
                oEvent=ev||event;
                //移动后,想要移动的距离
                var l=oEvent.clientX-disX;
                var t=oEvent.clientY-disY;
                var a=oDiv.offsetLeft;
                var b=oDiv.offsetHeight+oDiv.offsetLeft;
                var c=oDiv.offsetTop;
                var d=oDiv.offsetHeight+oDiv.offsetTop;

                var a2=oDiv2.offsetLeft;
                var b2=oDiv2.offsetHeight+oDiv2.offsetLeft;
                var c2=oDiv2.offsetTop;
                var d2=oDiv2.offsetHeight+oDiv2.offsetTop;
                if(b<a2||d<c2||c>d2||a>b2){
                    oDiv2.style.background='green'
                }
                else{
                    oDiv2.style.background='yellow'

                }
                //把l和t赋值给div的left和top让其达到运动的效果
                oDiv.style.left=l+'px';
                oDiv.style.top=t+'px';
            };
            document.onmouseup=function(){
                //鼠标释放后,把事件清空
                document.onmousedown=null;
                document.onmousemove=null
            }
        }
    };

</script>
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
</html>

 这红圈之外,让其颜色不变,在红圈之内,让其颜色改变。

if(b<a2||d<c2||c>d2||a>b2){
oDiv2.style.background='green'
}
else{
oDiv2.style.background='yellow'
}
 5、拖拽带框,也就是拖拽后有一个拖拽框,在确定拖拽位置后,那个框会消失

就是要达到上图的效果

代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
    #div1{width:100px;  height: 100px;  background-color: yellow; position: absolute}
    .box{position: absolute;border: dotted 1px black}
</style>
<script>
    window.onload=function(){
        var oDiv=document.getElementById('div1');
        var newDiv=document.createElement('div');
        oDiv.onmousedown=function(ev){
            oEvent=ev||event;
            //移动前的距离window的距离
            var disX=oEvent.clientX-oDiv.offsetLeft;
            var disY=oEvent.clientY-oDiv.offsetTop;
            document.onmousemove=function(ev){
                oEvent=ev||event;
                //移动后,想要移动的距离
                var l=oEvent.clientX-disX;
                var t=oEvent.clientY-disY;
                newDiv.className='box';
                newDiv.style.width=oDiv.offsetWidth-2+'px';
                newDiv.style.height=oDiv.offsetHeight-2+'px';
                document.body.appendChild(newDiv);
                oDiv.style.opacity=0.5;
                //把l和t赋值给div的left和top让其达到运动的效果
                newDiv.style.left=l+'px';
                newDiv.style.top=t+'px';
            };
            document.onmouseup=function(){
                //鼠标释放后,把事件清空
                document.onmousedown=null;
                document.onmousemove=null;
                document.body.removeChild(newDiv);
                oDiv.style.left=newDiv.style.left;
                oDiv.style.top=newDiv.style.top;
                oDiv.style.opacity=1;
            }
        }
    }
</script>
<body>
<div id="div1" ></div>
</body>
</html>

原理就是:当鼠标按下时,创建一个div,当鼠标抬起时,删除新创建的div,注意的一点就是:这时候移动的不是实际小块的位置,而是新建div的位置,让新建div移到某一位置后,再把新建div的left和top赋给小块的left和top,这样就达到边框先移动,移到某一位置后,真实的物体再到这一位置。

  6、利用div改变其父级的大小,就像实现博客园写随笔的的框大小的调整

代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
    #div1{width:10px;  height: 10px;bottom: 0;  right: 0; background-color: red; position: absolute}
    #div2{width:100px;  height: 100px;  background-color: green; position: relative}
</style>
<script>
    window.onload=function(){
        var oDiv=document.getElementById('div1');
        var oDiv2=document.getElementById('div2');
        oDiv.onmousedown=function(ev){
            oEvent=ev||event;
            //移动前的距离window的距离
            var disX=oEvent.clientX-oDiv.offsetLeft;
            var disY=oEvent.clientY-oDiv.offsetTop;
            document.onmousemove=function(ev){
                oEvent=ev||event;
                //移动后,想要移动的距离
                var l=oEvent.clientX-disX+oDiv.offsetWidth;
                var t=oEvent.clientY-disY+oDiv.offsetHeight;
                //把l和t赋值给div的left和top让其达到运动的效果
                oDiv2.style.width=l+'px';
                oDiv2.style.height=t+'px';
            };
            document.onmouseup=function(){
                //鼠标释放后,把事件清空
                document.onmousedown=null;
                document.onmousemove=null
            }
        }
    }
</script>
<body>
<div id="div2"><div id="div1"></div></div>
</body>
</html>

原理:和基本拖拽的唯一区别就是两点,一、父级  position是relative   子集position是absolute,这样保证子集的父级内,bottom:0和right:0让子集在右下角

       二、这时候拖拽改变了不是原物体的位置,而是把拖拽到某一位置的坐标,赋给父级div的宽度,注意:是style.width,它是一个字符串 带'px',height类似,这样就形成了一个改变父级边框大小的效果。

总结:

拖拽是常见的一种交互效果,掌握拖拽也对我们熟悉页面结构有很大帮助,下面附一张我珍藏好久的牛x图,了解各种宽高之间的区别


原文地址:https://www.cnblogs.com/dirkhe/p/6278809.html