利用onmousedown和dragstart分别实现网页拖拽效果

时间:2024-03-31 14:14:37

平常我们写网页拖拽的时候,一般都是通过mousedown+mousemove+mouseup这种方式来模拟出拖拽的效果的,今天看书的时候,偶然看到原来浏览器早就支持了原生的拖拽事件,那就是dragstart+drag+dragend这一套东西。

不难理解,看字面意思就知道这是开始拖拽+拖拽+完成拖拽分别触发的事件。

用这种原生的拖拽方式未必会比监听鼠标的方式好(特别是扩展性不够强),但至少我感觉相同的一段拖拽效果,用dragstart方式会要少写一些代码(省了碰撞检测不是)。

我们来先上一段代码,是监听鼠标事件模拟出的网页拖拽效果。当然你与我的方式未必相同,但想来应该大同小异。

利用onmousedown和dragstart分别实现网页拖拽效果Javascript利用onmousedown和dragstart分别实现网页拖拽效果
 1 window.onload =function(){
 2 
 3             var oBody = document.body;
 4             var oShow = document.getElementById('show');
 5             var aImg = document.getElementById('menu').getElementsByTagName('img');
 6             var moveable = false;
 7 
 8             for (var i=0; i<aImg.length; i++) {
 9                 
10                 aImg[i].onmousedown = function(ev){
11                     var ev = ev || window.event;
12                     var This = this;
13 
14                     //alert(document.documentElement.scrollTop)
15 
16                     var clonImg = document.createElement('img');
17                     clonImg.id = 'clonimg';
18                     clonImg.src= This.getAttribute('src');
19                     clonImg.style.position = 'absolute';
20                     clonImg.style.left = ev.clientX +'px';
21                     clonImg.style.top = ev.clientY +'px';
22                     clonImg.style.width = 150+'px';
23                     clonImg.style.opacity = 0.5;
24                     clonImg.style.filter = 'alpha(opacity=50)';
25 
26                     oBody.appendChild(clonImg);
27 
28                     //这是解决ie7下的一个兼容bug--来自妙味
29                     if(This.setCapture){
30                         This.setCapture();
31                     }
32                     
33                     document.onmousemove = function(ev){
34                         var ev = ev || window.event;
35                         clonImg.style.left = ev.clientX+ 'px';
36                         clonImg.style.top = ev.clientY+ 'px';
37                     };
38                     
39                     document.onmouseup = function(){
40 
41                         document.onmousemove = null;
42                         document.onmouseup = null;
43                         if(clonImg.releaseCapture){
44                             clonImg.releaseCapture();
45                         }
46                         if(runInto(clonImg,oShow)){
47                             clonImg.style.opacity = 1;
48                             clonImg.style.filter = 'alpha(opacity=100)';
49                         }
50                         else{
51                             oBody.removeChild(clonImg);
52                         }
53                     };
54                     ev.stopPropagation();
55                     return false;
56                     
57                 };
58                 
59             }
60             
61         }
62 
63         function runInto(obj1,obj2){//碰撞检测
64     
65             var L1 = obj1.offsetLeft;
66             var T1 = obj1.offsetTop;
67             var R1 = L1 + obj1.offsetWidth;
68             var B1 = T1 + obj1.offsetHeight;
69             
70             var L2 = obj2.offsetLeft;
71             var R2 = L2 + obj2.offsetWidth;
72             var T2 = obj2.offsetTop;
73             var B2 = T2 + obj2.offsetHeight;
74 
75             if( R1<=L2 || L1>=R2 || T1>=B2 || B1<=T2 ){
76                 return false;
77             }
78             else{
79                 return true;
80             }
81         };
通过mousedown方式实现拖拽

 

顺便附上我的网页结构和css代码还有实际效果图。

利用onmousedown和dragstart分别实现网页拖拽效果利用onmousedown和dragstart分别实现网页拖拽效果
1 <div id="main">
2         <div id="menu">
3             <a href="#"><img src="images/a.jpg" alt=""></a>
4             <a href="#"><img src="images/b.jpg" alt=""></a>
5             <a href="#"><img src="images/c.jpg" alt=""></a>
6         </div>
7         <div id="show"></div>
8     </div>
HTML

 

利用onmousedown和dragstart分别实现网页拖拽效果利用onmousedown和dragstart分别实现网页拖拽效果
*{ padding: 0; margin: 0;}
        #main{position: relative;}
        #menu{ position: absolute; left: 30px; top: 30px;}
        #menu img{ display: block; width: 150px; margin: 0px 0 20px;}
        #show{ position: absolute; left: 400px; top: 30px; width: 800px; height: 500px; border: 1px solid #f00;}
CSS

利用onmousedown和dragstart分别实现网页拖拽效果

同样的html结构,我们来看看dragstart方式实现拖拽的代码。

首先要说明的一点是浏览器本身拖拽事件是dragstart没错,但是我们接受拖拽的元素却是另一种方式。

我们在html中对于普通的元素只能拖拽并不能接收拖拽元素,大多时候默认只有input才能够接收拖拽元素,这时候我们需要做一些处理才能够让普通的元素接收拖拽元素。

我是在高程中学到的方式,看书总是能够让我们获得未知的知识。

我们只需要清除目标元素的dragenter(进入目标元素时触发)、dragover(在目标元素中移动会持续触发)、drop(拖拽完成并且拖拽元素处于目标元素中时会触发)三个事件就能够让普通的html元素变成可以接受拖拽元素的元素。

书上提到最开始是由ie4引入拖拽功能(dragstart等),不过当时只能支持input接收拖拽元素,不过ie5以上开始支持所有元素。Firefox、chrome等也相继提供支持。所以兼容问题应该不会很大。我这边测试过ie7+能够正常拖拽无误。

拖拽之后是通过dataTransfer对象存储拖拽的对象,HTML5可以提供更加复杂对象存储,不过之前的浏览器版本可能只支持图片或者链接的URL和文字,因此我们如果要进行一些复杂对象的拖拽,可能需要在dragstart时手动进行存储,之后在手动读取。

具体的实现方式来看下我的代码。部分知识已在注释中提到,可方便大家阅读。

利用onmousedown和dragstart分别实现网页拖拽效果利用onmousedown和dragstart分别实现网页拖拽效果
 1 window.onload =function(){
 2 
 3             var oShow = document.getElementById("show");
 4 
 5             //方法取自高程第三版482-483页
 6             //改变普通元素为拖拽目标元素,阻止默认行为,让show变为可接受拖拽的元素
 7             //dragenter拖拽元素到达目标元素时触发的事件
 8             addEvent(oShow,"dragenter",function(event){
 9                 eventPreventdefault(event);
10             })
11             //dragover拖拽元素在目标元素中移动时触发
12             addEvent(oShow,"dragover",function(event){
13                 eventPreventdefault(event);
14             })
15             //鼠标松开拖拽元素并且拖拽元素处于目标元素之中,就会执行drop事件
16             addEvent(oShow,"drop",function(event){
17                 
18                 //dataTransfer对象用于存储拖拽的数据(html5之前只支持url和text2种方式,因此如果要兼容的话,可以在dragstart时将复杂对象存储。)
19                 var dataTransfer = event.dataTransfer;
20                 var drawImgUrl = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");
21                 var clonImg = document.createElement('img');
22                 clonImg.src= drawImgUrl;
23                 clonImg.style.width = 150+'px';
24                 clonImg.style.position = 'absolute';
25                 clonImg.style.left = (event.clientX - oShow.offsetLeft) + 'px';
26                 clonImg.style.top = (event.clientY - oShow.offsetTop) + 'px';
27                 oShow.appendChild(clonImg)
28                 eventPreventdefault(event);
29             })
30         }
31 
32         //addEvent为元素添加事件
33         function addEvent(obj, sEvent, fn){
34             //attachEvent支持IE下添加事件,格式obj.attachEvent(event,function);event带on,如onclick
35             if(obj.attachEvent){
36                 obj.attachEvent('on'+sEvent, fn);
37             }
38             else{
39                 //addEventListener支持Firefox、Chrome等W3C浏览器,格式addEventListener(event,obj,false),event不带on,如click,false为定值不用更改
40                 obj.addEventListener(sEvent, fn, false);
41             }
42         };
43 
44         //取消默认行为
45         function eventPreventdefault(event){
46             if(event && event.preventDefault){
47                 event.preventDefault();
48             }else{
49                 window.event.returnValue = false;//低版本ie不支持prevendefault()只能通过returnValue取消默认行为
50             }
51         }
Javascript通过dragstart方式实现网页拖拽效果

 

利用onmousedown和dragstart分别实现网页拖拽效果

这是通过dargstart方式实现的效果,基本相似,由于少了碰撞检测的部分,所以代码应该会相对少一些,当然如果需要进行复杂的包含检测,依然的在drop中进行检测。

两种实现方式孰优孰劣我不知道,我并不擅长性能方面的测试,但我想原生的方式应该会更加优秀一些。如果有人也有这方面的尝试,可以相互交流。