拖拽的原生实现与H5实现

pageX,pageY:点击位置相对于html元素的坐标,单位为像素(加上滚动距离的,没有滚动时与clientX相同)

clientX,clientY:点击位置相对于视口(viewport)的坐标,单位为像素(不包含滚动条)

screenX,screenY:点击位置相对于显示屏幕的坐标,单位为设备硬件的像素

scrollHeight,scrollWidth:没有滚动条时,元素内容的高度/宽度

scrollLeft,scrollTop:被隐藏在内容区域左侧/上方的像素数。通过设置这个可以改变元素的滚动位置

1.原生拖拽实现

#div1{
  width: 100px;
  height:100px;
  background: pink;
  position: absolute;
}
    
<div id="div1">sonya test</div> 

<div id="div1"></div> 

<div id="div1"><img src="ele.png" alt=""></div>

window.onload = function(){
  var oDiv = document.getElementById("div1");
  var disX = 0;
  var disY = 0;

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

    //在IE下,如果选中元素拖拽就会有问题:IE设置全局捕获:setCapture 释放全局捕获:releaseCapture
    if(oDiv.setCapture){
      oDiv.setCapture();
    }
    
    //div加事件会迟钝
    document.onmousemove = function(e){
      var e = e || window.event;
      var iLeft = e.clientX - disX;
      var iTop = e.clientY - disY;

      if(iLeft < 0){
        iLeft = 0;
      }
      if(iTop < 0){
        iTop = 0;
      }
      if(iLeft > document.documentElement.clientWidth - oDiv.offsetWidth){
        iLeft = document.documentElement.clientWidth - oDiv.offsetWidth;
      }
      if(iTop > document.documentElement.clientHeight - oDiv.offsetHeight){
        iTop = document.documentElement.clientHeight - oDiv.offsetHeight;
      }

      oDiv.style.left = iLeft + "px";
      oDiv.style.top = iTop + "px";
    };

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

    //在标准浏览器下 如果拖拽一个空的标签,就会有问题:return false
    //在标准浏览器下 拖拽图片会有问题(会粘着,点一下才能释放):return false
    //return false;
  };
};

2.HTML5实现

window.onload = function(){
  var p3 = document.getElementById("div1");
  p3.ondragstart=function(e){
        console.log('事件源p3开始拖动');
        //记录刚一拖动时,鼠标在飞机上的偏移量
        offsetX= e.offsetX;
        offsetY= e.offsetY;
        console.log(e);
    }
    p3.ondrag=function(e){
        console.log('事件源p3拖动中');
        var x= e.pageX;
        var y= e.pageY;
        console.log(x+'-'+y);
        //drag事件最后一刻,无法读取鼠标的坐标,pageX和pageY都变为0
        if(x==0 && y==0){
            return; //不处理拖动最后一刻X和Y都为0的情形
        }
        x-=offsetX;
        y-=offsetY;

        p3.style.left=x+'px';
        p3.style.top=y+'px';
    }
    p3.ondragend=function(){
        console.log('源对象p3拖动结束');
    }
}

2.1 H5拖拽小例子

#div1{
  width: 100px;
  height:100px;
  background: pink;
  position: absolute;
}
li{
  width: 100px;
  height: 30px;
  border:1px #000 solid;
  margin:20px;
  list-style: none;
}
    
<ul>
  <li draggable="true">111</li>
  <li draggable="true">222</li>
  <li draggable="true">333</li>
</ul>
<div id="div1"></div>
  
  
window.onload = function(){
  var aLi = document.getElementsByTagName("li");
  var oDiv = document.getElementById("div1");
  var iNow = 0;

  for(var i=0;i<aLi.length;i++){
    //拖拽前触发
    aLi[i].ondragstart = function(){
      this.style.background = "yellow";
    };

    //拖拽结束触发
    aLi[i].ondragend = function(){
      this.style.background = "blue";
    };

    //开始与结束之间连续触发
    aLi[i].ondrag = function(){
      document.title = iNow++;
      //console.log(iNow++);
    };
  }

  //相当于onmouseover元素被拖放到放置目标上
  oDiv.ondragenter = function(e){
    this.style.background = "green";
    console.log("e-->",e);
    e.preventDefault();  //阻止默认事件,元素就可以释放了
  };

  //相当于onmouseout
  oDiv.ondragleave = function(){
    this.style.background = "red";
  };

  //进入目标、离开目标之间,连续触发
  oDiv.ondragover = function(e){
    e.preventDefault();  //阻止默认事件,元素就可以释放了
    document.title = iNow++;
    //console.log(iNow++);
  };

  //释放鼠标的时候触发
  oDiv.ondrop = function(e){
    this.style.background = "#ccc";
    alert("鼠标已经释放");
    e.preventDefault(); //阻止默认事件:防止打开拖拽元素的url
  };

  //被拖放的元素在放置目标的范围内移动 会连续触发dragover
  //元素被拖出放置目标 dragleave
  //元素被放倒了放置目标中 drop
};

3.dataTransfer对象

<ul>
  <li draggable="true">111</li>
  <li draggable="true">222</li>
  <li draggable="true">333</li>
</ul>

<a href="http://www.baidu.com">go baidu</a>

<div id="div1"></div> 

window.onload = function(){
  var aLi = document.getElementsByTagName("li");
  var aA = document.getElementsByTagName("a");
  var oDiv = document.getElementById("div1");

  for(var i=0;i<aLi.length;i++){
    aLi[i].ondragstart = function(e){
      console.log("e-->",e,e.dataTransfer);
      this.style.background = "yellow";
      e.dataTransfer.setData("a","hello");  //存储一个键值对,value必须是字符串
      e.dataTransfer.effectAllowed = "all";  //放置目标能够接受什么操作
    };

    aLi[i].ondragend = function(){
      this.style.background = "blue";
    };
  }

  for(var i=0;i<aA.length;i++){
    aA[i].ondragstart = function(e){
      this.style.background = "yellow";
      e.dataTransfer.setData("a","hello");
      e.dataTransfer.effectAllowed = "link";
    };

    aA[i].ondragend = function(){
      this.style.background = "blue";
    };
  }

  oDiv.ondragenter = function(){
    this.style.background = "green";
  };

  oDiv.ondragLeave = function(){
    this.style.background = "red";
  };

  oDiv.ondragover = function(e){
    e.preventDefault();
    e.dataTransfer.dropEffect = "link";  //被拖拽元素能够执行哪种行为
  };

  oDiv.ondrop = function(e){
    this.style.background = "#ccc";
    alert( e.dataTransfer.getData("a") );
    alert( e.dataTransfer.types);
  };
};

4.桌面文件拖拽到页面

<div id="div1">sonya test</div>

window.onload = function(){    
    var oDiv = document.getElementById('div1');  

    oDiv.ondragenter = function(){  //相当于onmouseover          
        this.style.background = 'green';  
    };  

    oDiv.ondragleave = function(){  //相当于onmouseout  		          
        this.style.background = 'red';  		          
    };  

    oDiv.ondragover = function(ev){ //进入目标、离开目标之间,连续触发        
        ev.preventDefault();  //阻止默认事件:元素就可以释放了 :不然会打开文件    
        ev.dataTransfer.dropEffect = 'link';  //真对外部文件      
    };  

    oDiv.ondrop = function(ev){  //释放鼠标的时候触发       
        ev.preventDefault();  //阻止默认行为  不然会打开文件       
        this.style.background = '#ccc';              
        var oFR = new FileReader();       
        var list = ev.dataTransfer.files;  //当前拖拽的那个文件(返回的一个文件列表)         
        alert(list.length);  
        alert(list[0].type);  //type : 文件类型  
        
        oFR.readAsDataURL(list[0]);  

        oFR.onload = function(){ //读取完成,触发事件  		              
            alert(this.result);  // 读取到的信息  		              
        };  
    };  
};

5.垃圾箱删除小例子

<ul>  
    <li draggable="true">a</li>  
    <li draggable="true">b</li>  
    <li draggable="true">c</li>  
</ul>  
<div id="div1">垃圾箱</div>  
  
window.onload = function(){  
  var aLi = document.getElementsByTagName('li');  
  var oDiv = document.getElementById('div1');  
  var iNow = 0;  

  var targetLi = null;  

  for(var i=0;i<aLi.length;i++){  
      aLi[i].ondragstart = function(ev){ //拖拽前触发  		          
          this.style.background = 'yellow';  		              
          ev.dataTransfer.setData('text',this.innerHTML);  //存储一个键值对 : value值必须是字符串  		              
          targetLi = this;  		          
      };  

      aLi[i].ondragend = function(){  //拖拽结束触发  		          
          this.style.background = 'blue';  		          
      };  
  }  

  oDiv.ondragenter = function(){  //相当于onmouseover  		          
      this.style.background = 'green';  		          
  };  

  oDiv.ondragleave = function(){  //相当于onmouseout  
      this.style.background = 'red';  		          
  };  

  oDiv.ondragover = function(ev){ //进入目标离开目标之间连续触发  	
    ev.preventDefault();  //阻止默认事件元素就可以释放了          
  };  

  oDiv.ondrop = function(ev){  //释放鼠标的时候触发  		      
      this.style.background = '#ccc';    		      
      var oText = ev.dataTransfer.getData('text');  		      
      if(targetLi){  
          targetLi.parentNode.removeChild(targetLi);  
          this.innerHTML = '删除的是:'+oText;  
      }  		      
  };  		      
};  

代码参考:梦龙小站——H5拖拽1

代码参考:梦龙小站——H5拖拽2

代码参考:梦龙小站——H5拖拽3

代码参考:梦龙小站——H5拖拽4

Table of Contents