自己造轮子写个原生拖放,要做到简单调用,考虑拖放对象所在的环境,还要兼容老IE,还是挺锻炼人的。
主要碰到几个问题:
- 关于冒泡和阻止默认事件,以前的理解都很粗略,自己写的时候才知要细分。
一是要阻止事件传递,即事件冒泡,老IE里是ev.cancelBubble=true,其他浏览器是ev.stopPropagation(),要在onmousedown的时候就定义好;
然后是阻止默认事件,主要是为了防止图片无法拖动的问题,要在onmousemove的时候,老IE里是ev.returnValue=false; 其他浏览器ev.preventDefault() - 拖动过程中鼠标移出物件,就要把事件方法在document上复制一遍:document.onmousemove=_self.onmousemove; 并且考虑到拖放结束的时候鼠标可能是在任意位置,那就干脆把onmouseup方法写在document上
- 单纯的拖放物件其实没什么用,实际应用的时候肯定会给拖放增加范围,比如自制的滚动条,幻灯效果等。所以给拖放对象的父级元素作边界。于是又重温了各种位置取值的兼容问题,getBoundingClientRect()是一个很有用的函数,不过在老IE里面取不到宽高,所以要自己计算一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | function dragObj(obj, objEdge){ //obj为拖放对象;objEdge为布尔值,为true则obj的父对象作为拖放的边界 function getScrollOffsets(_w) {//获取页面的滚动位置函数 _w = _w || window; //for all and IE9+ if (_w.pageXOffset != null) return { x: _w.pageXOffset, y: _w.pageYOffset }; //for IE678 var _d = _w.document; if (document.compatMode == "CSS1Compat") return { //for IE678 x: _d.documentElement.scrollLeft, y: _d.documentElement.scrollTop }; //for other mode return { x: _d.body.scrollLeft, y: _d.body.scrpllTop }; } var _self=obj; this._self=_self; if(objEdge) {//初始化边界的属性,如果是图片的话必须页面加载初始化,否则探测不到图片的宽高。也可以放在点击事件处理程序中,这样不需要等页面加载完毕 var _edge=_self.parentNode; this._edge=_edge; //初始化目标样式 if(!_self.style.top) { _self.style.top=( _self.getBoundingClientRect().top-_edge.getBoundingClientRect().top )+"px"; } if(!_self.style.left) { _self.style.left=( _self.getBoundingClientRect().left-_edge.getBoundingClientRect().left )+"px"; } if(!_self.style.position) _self.style.position="absolute"; if(!_self.style.display || _self.style.display=="inline") _self.style.display="block"; //初始化边界样式和移动固定区域 if(!_edge.style.display || _edge.style.display=="inline") _edge.style.display="block"; var edgeSizeWidth=_edge.getBoundingClientRect().right-_edge.getBoundingClientRect().left;//边界尺寸 var edgeSizeHeight=_edge.getBoundingClientRect().bottom-_edge.getBoundingClientRect().top; var dragObjSizeWidth=_self.getBoundingClientRect().right-_self.getBoundingClientRect().left;//拖动对象尺寸 var dragObjSizeHeight=_self.getBoundingClientRect().bottom-_self.getBoundingClientRect().top; _edge.w=edgeSizeWidth-dragObjSizeWidth; _edge.h=edgeSizeHeight-dragObjSizeHeight; } else {//无边界元素,在页面自由移动 if(!_self.style.top) {_self.style.top = _self.getBoundingClientRect().top + getScrollOffsets().y + "px"} if(!_self.style.left) {_self.style.left = _self.getBoundingClientRect().left + getScrollOffsets().x + "px"} if(!_self.style.position || _self.style.position!="absolute" ) _self.style.position="absolute"; if(!_self.style.display || _self.style.display=="inline") _self.style.display="block"; var _edge=document.body; } _self.mousePosition= function(ev){ ev = ev || window.event; var target = ev.target || ev.srcElement; // 获得事件源 if(ev.pageX || ev.pageY){ return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop }; } _self.onmousedown=function(ev){ ev = ev || window.event; var startY=_self.mousePosition(ev).y-parseInt(_self.style.top); var startX=_self.mousePosition(ev).x-parseInt(_self.style.left); if (ev && ev.preventDefault) {//阻止事件传播冒泡 ev.stopPropagation(); }else if (document.all){ ev.cancelBubble=true; } _self.onmousemove=function(ev){ ev = ev || window.event; var poX=_self.mousePosition(ev).x-startX; var poY=_self.mousePosition(ev).y-startY; if(objEdge){ if(poX<0) poX=0; if(poX>_edge.w) { poX=_edge.w; } if(poY<0) poY=0; if(poY>_edge.h) { poY=_edge.h; } } _self.style.left=poX+"px"; _self.style.top=poY+"px"; if (ev && ev.preventDefault) {//阻止默认事件,比如图片拖动问题 ev.preventDefault(); }else if (document.all){ ev.returnValue = false; } } _self.onmouseout=function(ev){//如果鼠标移出了物件,用文档接受鼠标事件 document.onmousemove = _self.onmousemove; } document.onmouseup=function(){//放开鼠标,释放所有相关事件 _self.onmousemove=null; document.onmousemove=null; _self.onmouseout=null; } } } |
兼容IE6-11以及其他主流浏览器,调用方法:
1 2 | var d1=new dragObj(document.getElementById("objID"), true);//父级元素自动作为边界 var d2=new dragObj(document.getElementById("objID"), false);//无边界,在窗口内部自由拖动,false也可以省略 |
本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/501.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。
本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。