




已阅读5页,还剩22页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
简易而又灵活的Javascript拖拽框架简易而又灵活的Javascript拖拽框架(一)一、开篇最近在做js拖拽的时候,发现了一个强大而又灵活的拖拽框架,(之前用了代码混淆器,还好代码比较短,我就翻译过来了)利用这个框架不仅能实现简单的拖动,更能轻易的实现各种复杂的拖放功能。这一篇先实现最简单的拖拽,稍微复杂的拖放将在后面的文章里写出来。二、代码先把代码贴出来CodevarDrag=obj:null,init:function(handle,dragBody,e)if(e=null)handle.onmousedown=Drag.start;handle.root=dragBody;if(isNaN(parseInt(handle.root.style.left)handle.root.style.left=0px;if(isNaN(parseInt(handle.root.style.top)handle.root.style.top=0px;/确保后来能够取得top值handle.root.onDragStart=newFunction();handle.root.onDragEnd=newFunction();handle.root.onDrag=newFunction();if(e!=null)varhandle=Drag.obj=handle;e=Drag.fixe(e);vartop=parseInt(handle.root.style.top);varleft=parseInt(handle.root.style.left);handle.root.onDragStart(left,top,e.pageX,e.pageY);handle.lastMouseX=e.pageX;handle.lastMouseY=e.pageY;document.onmousemove=Drag.drag;document.onmouseup=Drag.end;,start:function(e)varhandle=Drag.obj=this;e=Drag.fixEvent(e);vartop=parseInt(handle.root.style.top);varleft=parseInt(handle.root.style.left);/alert(left)/一般情况下lefttop在初始的时候都为0handle.root.onDragStart(left,top,e.pageX,e.pageY);handle.lastMouseX=e.pageX;handle.lastMouseY=e.pageY;document.onmousemove=Drag.drag;document.onmouseup=Drag.end;returnfalse;,drag:function(e)/这里的this为document所以拖动对象只能保存在Drag.obj里e=Drag.fixEvent(e);varhandle=Drag.obj;varmouseY=e.pageY;varmouseX=e.pageX;vartop=parseInt(handle.root.style.top);varleft=parseInt(handle.root.style.left);/这里的top和left是handle.root距离浏览器边框的上边距和左边距varcurrentLeft,currentTop;currentLeft=left+mouseX-handle.lastMouseX;currentTop=top+(mouseY-handle.lastMouseY);/上一瞬间的上边距加上鼠标在两个瞬间移动的距离得到现在的上边距handle.root.style.left=currentLeft+px;handle.root.style.top=currentTop+px;/更新当前的位置handle.lastMouseX=mouseX;handle.lastMouseY=mouseY;/保存这一瞬间的鼠标值用于下一次计算位移handle.root.onDrag(currentLeft,currentTop,e.pageX,e.pageY);/调用外面对应的函数returnfalse;,end:function()document.onmousemove=null;document.onmouseup=null;Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style.left),parseInt(Drag.obj.root.style.top);Drag.obj=null;,fixEvent:function(e)/格式化事件参数对象if(typeofe=undefined)e=window.event;if(typeofe.layerX=undefined)e.layerX=e.offsetX;if(typeofe.layerY=undefined)e.layerY=e.offsetY;if(typeofe.pageX=undefined)e.pageX=e.clientX+document.body.scrollLeft-document.body.clientLeft;if(typeofe.pageY=undefined)e.pageY=e.clientY+document.body.scrollTop-document.body.clientTop;returne;使用方法Drag.init(handle,dragBody);这样可以让鼠标拖动元素。Handle为拖动的把手,dragBody是在拖动时需要移动的元素。如果需要更高级的控制拖动或者拖放的话,可以给dragBody设置三个方法dragBody.onDragStart=function(left,top,mouseX,mouseY)onDrag(left,top,mouseX,mouseY)onDragEnd(left,top,mouseX,mouseY)这四个参数分别是:拖动对象的left属性、拖动对象的top属性(此时拖动对象的position为absolute)、鼠标当前的x、鼠标当前的y。在每个过程中都可以通过四个参数来更精确的控制拖动的每个过程,更主要的是我们不需要去管被鼠标拖动的元素是怎么移动的,这些都在框架中已经做好了,这让拖拽看起来更整洁。框架具体是怎么运转的,其实很简单三、原理Drag有几个成员Drag.obj用来存放鼠标正在被拖动的元素,只有在鼠标按下过后才会赋值,鼠标松开便为空了。便于在这几个方法之间都能够轻易的找到正在被拖动的元素。Drag.init主要是用来订阅handle的onmousedown事件,所以handle一旦点击,则会执行Drag.start方法。Drag.start是用来注册document的mousemove和mouseup事件的,而且会调用我们定义的dragBody.onDragStart方法(这里的dragBody就是通过Drag.obj来获得的),以便处理框架以外需要处理的事情。Mousemove的时候会不断的触发Drag.drag方法,这个方法主要是控制dragBody的移动(通过前后两个瞬间的位移差来调整dragBody的位置),以及调用外部的dragBody.onDrag方法,处理框架以外的事情。Document的mouseup方法,调用外部的onDragEnd方法,释放document绑定的两个事件,以及将临时的obj置为空四、示例下载简易而又灵活的Javascript拖拽框架(二)一、开篇在上一篇中,似乎不出来这个框架有多强大。是因为我们实现的效果太简单了,还不足以体现框架的强大和灵活,在这一节中,用这个灵活的框架轻易的来实现拖放!二、原理框架的原理在上一篇文章中介绍了,这里就不在重复,直接开始使用这个框架了首先通过Drag.init来注册拖动组件;分析:1、拖动开始的时候将dragGhost插入到鼠标拖动的那个元素,鼠标拖动的元素的position为absolutedragGhost为拖动过程中指示拖动元素的当前位置的元素2、拖动正在进行的时候根据当前鼠标的位置或者正在被鼠标拖动的元素的位置 和需要排列的各种元素来比较,以确定将dragGhost放在哪个地方。具体的分析,就是遍历拖动元素的各个兄弟元素,从第一元素起,一旦发现某个元素的x和y比鼠标的x和y大的话,则将dragGhost添加到这个元素之前。3、拖动结束的时候将dragGhost替换为被拖动的元素,然后将dragGhost隐藏。这样就让思路很清晰,不必再花精力去管元素是怎么随着鼠标走的,而且我们的却很精确的控制了整个拖放过程,所以说这个框架很强大很灵活三、代码CodefunctionfindPosX(obj)/辅助函数得到元素左边与浏览器左边的边距varcurleft=0;if(obj&obj.offsetParent)while(obj.offsetParent)curleft+=obj.offsetLeft;obj=obj.offsetParent;elseif(obj&obj.x)curleft+=obj.x;returncurleft;/+document.body.scrollLeft-document.body.clientLeft;functionfindPosY(obj)/辅助函数得到元素上边与浏览器上边的边距varcurtop=0;if(obj&obj.offsetParent)while(obj.offsetParent)curtop+=obj.offsetTop;obj=obj.offsetParent;elseif(obj&obj.y)curtop+=obj.y;returncurtop;/+document.body.scrollTop-document.body.clientTop;vardragGhost;varcontainer;window.onload=function()dragGhost=document.getElementById(dragGhost);container=document.getElementById(container);varnodes=container.getElementsByTagName(li);for(vari=0;inodes.length;i+)varli=nodesi;if(li.id!=dragGhost)newdragItem(li);varisIE=document.all;functiondragItem(item)Drag.init(item,item);item.onDragStart=function(left,top,mouseX,mouseY)this.style.left=findPosX(this);this.style.top=findPosY(this);this.style.position=absolute;/将ghost插入到当前位置dragGhost.style.display=block;dragGhost.style.width=isIE?this.offsetWidth:this.offsetWidth-2;/边框问题dragGhost.style.height=isIE?this.offsetHeight:this.offsetHeight-2;this.parentNode.insertBefore(dragGhost,this);item.onDrag=function(left,top,mouseX,mouseY)varnodes=container.getElementsByTagName(li);varwidth=this.offsetWidth;varheight=this.offsetHeight;for(vari=0;inodes.length+1;i+)if(nodesi=null)container.appendChild(dragGhost);/拖动最后一项break;if(nodesi.id=dragGhost|nodesi=this)continue;if(mouseXfindPosX(nodesi)+width&mouseYfindPosY(nodesi)+height)container.insertBefore(dragGhost,nodesi);break;item.onDragEnd=function(left,top,mouseX,mouseY)container.insertBefore(this,dragGhost);this.style.position=static;this.style.display=block;dragGhost.style.display=none;简易而又灵活的Javascript拖拽框架(三)一、开篇 这是这个拖拽系列的第三篇了,第一篇简单的介绍了一下这个拖拽框架,第二篇用这个框架做了一个Tab标签的拖放。这次用这个拖拽框架做一个更复杂一点的效果跨列拖放。就像iGoogle和netvibes的个性页面布局那样。二、原理框架在第一篇做了介绍,这里直接使用。首先要找到每个可以拖动的item,对于每个拖动的item,对其注册组件Drag.init(handle,dragBody);并且要把这个对象所在的列赋值给这个对象还是分三个步骤说这个拖放的过程 1、鼠标拖动开始的时候,除了要将dragGhost放到当前被拖动的对象原来的位置上,还要记录每一列的左边距,当然还是要设置被拖动对象的position2、鼠标拖动的过程中先找到拖动对象是在哪一列,通过现在拖动对象的位置和在拖动开始时记录的列的左边距相比较,得出当前拖动对象在哪一列。如果在原来那一列上,则不用管了,如果在别的列上,则将dragGhost插入到这个新的列中去(用column.appendChild插入到最后)。无论是本来就在这一列的元素还是从别的列拖过来的元素,都得让拖动对象与他所在的列的每一个元素的纵坐标相比较,得出应该在这一列的什么位置,将dragGhost插入(用column.insertBefore)。至于怎么找到拖动元素应该放在这一列的什么位置,这个原理和上边找列的原理差不多,只是比较的是纵坐标的值,比较的对象是本列的所有对象(注意,遍历的时候一定要排除dragGhost和本身,要不然在本列不能向下拖动)。 3、拖动完成将ghost替换为被拖动的元素,设置相应的样式三、代码Code/-Utility-functionfindPosX(obj)/辅助函数得到元素左边与浏览器左边的边距varcurleft=0;if(obj&obj.offsetParent)while(obj.offsetParent)curleft+=obj.offsetLeft;obj=obj.offsetParent;elseif(obj&obj.x)curleft+=obj.x;returncurleft;/+document.body.scrollLeft-document.body.clientLeft;functionfindPosY(obj)/辅助函数得到元素上边与浏览器上边的边距varcurtop=0;if(obj&obj.offsetParent)while(obj.offsetParent)curtop+=obj.offsetTop;obj=obj.offsetParent;elseif(obj&obj.y)curtop+=obj.y;returncurtop;/+document.body.scrollTop-document.body.clientTop;vardragGhost=document.createElement(div);dragGhost.style.border=dashed1px#CCCCCC;dragGhost.style.background=white;dragGhost.style.display=none;dragGhost.style.margin=10px;varcontainer;varcolumns=;/-StartHere-window.onload=function()container=document.getElementById(container);for(vari=0;icontainer.childNodes.length;i+)if(container.childNodesi.className=column)/筛选出所有的列ff下的childNodes不可靠:columns.push(container.childNodesi);for(vari=0;icolumns.length;i+)varcolumn=columnsi;for(varj=0;jcolumn.childNodes.length;j+)varitem=column.childNodesj;if(item.className=item)item.column=column;/给每个拖拽对象要指明它属于哪一列而且这个属性会随着拖动而更新的newdragItem(item);varisIE=document.all;/-DragItem-functiondragItem(item)/item实际上是dragBody(拖动的时候移动的整体)/在这里需要根据item找到handle(能够拖动的把手)varhandle;for(vari=0;iitem.childNodes.length;i+)if(item.childNodesi.nodeName.toLowerCase()=h3)handle=item.childNodesi;break;if(!handle)return;Drag.init(handle,item);item.onDragStart=function(left,top,mouseX,mouseY)/开始拖动的时候设置透明度this.style.opacity=0.5;this.style.filter=alpha(opacity=50);dragGhost.style.height=isIE?this.offsetHeight:this.offsetHeight-2;/this指的是itemthis.style.width=this.offsetWidth;/因为初始的width为autothis.style.left=findPosX(this)-5;this.style.top=findPosY(this)-5;this.style.position=absolute;/将ghost插入到当前位置dragGhost.style.display=block;this.column.insertBefore(dragGhost,this);/记录每一列的左边距在拖动过程中判断拖动对象所在的列会用到this.columnsX=;for(vari=0;icolumns.length;i+)this.columnsX.push(findPosX(columnsi);item.onDrag=function(left,top,mouseX,mouseY)/先要判断在哪一列移动varcolumnIndex=0;for(vari=0;ithis.columnsXi)columnIndex=i;/如果columnIndex在循环中没有被赋值则表示当前拖动对象在第一列的左边/此时也把它放到第一列varcolumn=columnscolumnIndex;if(this.column!=column)/之前拖动对象不在这个列/将ghost放置到这一列的最下方column.appendChild(dragGhost);this.column=column;/然后在判断放在这一列的什么位置varcurrentNode=null;for(vari=0;ithis.column.childNodes.length;i+)if(this.column.childNodesi.className=item&this.column.childNodesi!=this/不能跟拖动元素自己比较否则不能在本列向下移动&topfindPosY(this.column.childNodesi)/从上到下找到第一个比拖动元素的上边距大的元素currentNode=this.column.childNodesi;break;if(currentNode)this.column.insertBefore(dragGhost,currentNode);else/拖到最下边没有任何一个元素的上边距比拖动元素的top大则添加到列的最后this.column.appendChild(dragGhost);item.onDragEnd=function(left,top,mouseX,mouseY)this.style.opacity=1;this.style.filter=alpha(opacity=100);this.column.insertBefore(this,dragGhost);this.style.position=static;this.style.display=block;this.style.width=auto;dragGhost.style.display=none;如果这样不方便观看,可以下载示例。四、示例下载简易而又灵活的Javascript拖拽框架(四)一、开篇似乎拖拽已经被写烂了,没得写的了,可是我这次又来了上一次写的是跨列拖放,这次我要带给大家的是跨页拖放。可以到这里来看看效果:示例效果说明:1、如果将方框拖动到页签上立刻释放掉的话,则会被添加到该页的第一列的第一个位置; 2、如果将方框拖动到页签上并且停留片刻的话,则页面就会转换到该页,这个时候可以在页签上释放,也可以将方框拖动到此页的具体位置释放。二、原理 我是在跨列拖放的基础上修改的代码,虽然仅仅是从跨“列”升级为跨“页“,但是这就意味着多了一个dimension。所以代码改动比较大,尤其是初始化的代码。为了弄清楚代码中的命名同时也便于阐述原理,我画了下面的图1、在拖动开始时,跟之前的跨列拖拽差不多,基本上不需要修改;2、在拖动的过程中,就需要判断拖动module时的鼠标是否是在某个tab上,如果在tab上,则把dragGhost(拖动中占位的虚线框)隐藏了,并且设置转换页面的timeout(注意:这个timeout不要设置重复了,而且如果鼠标就在本页上就不需要设置),在设置这个timeout的响应函数也要小心,必须先把拖动的module放到新的页面然后再转换页面,因为鼠标虽然拖动了module,但是在html代码中,这个module还是属于原来的页面(只是因为position为absolute才让它游离出来的),如果原来的页面因为页面转换而变得不可见了,那么鼠标拖动的module也会不翼而飞的。3、在拖动的过程中,如果鼠标不在某个tab上,首先要将timeout及时清除了,要不然在拖动时会莫名其妙的转换页面,剩下的跟页面内拖放是一样的计算方法来处理,也是先计算所在的列,然后计算再这个列的位置,在此不再累述。4、在拖动的过程中,注意维持module的column变量,这个变量对于拖放很重要,要及时而正确的更新。5、在拖动结束的时候,如果鼠标还在某个tab上(无论这个时候页面是不是因为鼠标的停留而改变),则把module放在这一页的第一列的第一个位置。如果不在tab上,那么和页面内拖放是一样的。无论怎样,在最后都要设置一些style以及更新个别变量,放置完毕。三、代码 原理说起来容易,写起来还是很麻烦的,而且得经过很多次测试才能成功的。 不过我总结出来几点: 1、对于任何一个对象,要分清楚这个对象是html对象还是我们自定义类的对象; 2、各种对象尽量少维持一些变量,要不然在每次动作发生的时候都会去更新一堆变量,那将是很麻烦的(或许可以将这些变量的设置封装成对象的方法); 主要代码如下:Codevarmodule=function(moduleElm)varself=this;this.elm=moduleElm;this.elm.module=this;this.column=moduleElm.column;this.page=this.column.page;this.handle=this.elm.getElementsByTagName(h3)0;/这里只是为了各个页面的module看起来不一样所以另外设置一下style/page的id也是为了这个目的而加的其他地方page的id是用不上的switch(this.page.id)casepage1:this.handle.style.backgroundColor=red;break;casepage2:this.handle.style.backgroundColor=blue;break;casepage3:this.handle.style.backgroundColor=black;break;casepage4:this.handle.style.backgroundColor=#CCCCCC;break;if(this.handle&this.elm)Drag.init(this.handle,this.elm);elsereturn;this.elm.onDragStart=function(left,top,mouseX,mouseY)/开始拖动的时候设置透明度this.style.opacity=0.5;this.style.filter=alpha(opacity=50);dragGhost.style.height=isIE?this.offsetHeight:this.offsetHeight-2;/this指的是itemthis.style.width=this.offsetWidth;/因为初始的width为autothis.style.left=findPosX(this)-5;this.style.top=findPosY(this)-5;this.style.position=absolute;/将ghost插入到当前位置dragGhost.style.display=block;self.column.insertBefore(dragGhost,this);/记录每一列的左边距在拖动过程中判断拖动对象所在的列会用到this.columnsX=;for(vari=0;iself.column.page.columns.length;i+)this.columnsX.push(findPosX(self.column.page.columnsi);this.elm.onDrag=function(left,top,mouseX,mouseY)this.currentTab=null;/判断是否在tab上for(vari=0;iXDrag.tabs.length;i+)vartabElm=XDrag.tabsi.elm;if(findPosX(tabElm)mouseX)&(findPosY(tabElm)mouseY)this.currentTab=XDrag.tabsi;break;if(this.currentTab!=null)if(dragGhost.parentNode)dragGhost.parentNode.removeChild(dragGhost);functionchangeTab()/先得把module放到当前的这一页/否则会随着tab的改变而消失varcurrentColumn=self.elm.currentTab.page.columns0;varflag=false;for(vari=0;icurrentColumn.childNodes.length;i+)if(currentColumn.childNodesi.nodeName.toLowerCase()=div)currentColumn.insertBefore(self.elm,currentColumn.childNodesi);flag=true;break;if(!flag)currentColumn.appendChild(this);self.column=currentColumn;/将拖动的module添加到这一页的第一列因为display还为absolute所以module还跟着鼠标在走self.elm.currentTab.select();XDrag.changeTabTimeoutId=null;/如果Timeout不为空(防止重复设置Timeout)而且移动到的tab不是当前的tab(如果是当前tab则不需要改变tab页了)if(XDrag.changeTabTimeoutId=null&this.currentTab!=XDrag.sele
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度河北省护师类之护士资格证题库与答案
- 2024年度河北省护师类之护士资格证高分通关题型题库附解析答案
- 2024年度河北省护师类之护师(初级)模拟试题(含答案)
- 2025江苏扬州拓普人才开发有限公司招聘劳务派遣工作人员4人笔试备考题库及一套完整答案详解
- 2025年东营市公务员考试行测试卷历年真题及答案详解(各地真题)
- 第2章 一元二次函数、方程和不等式 单元测试(含答案) 2024-2025学年高中数学湘教版(2019)必修第一册
- 山东省济宁市2024-2025学年高二下学期期中教学质量检测数学试题(解析版)
- 房地产项目中的多方协作与协调
- 色谱教学课件动画
- 基于深度强化学习的双层UAV计算卸载策略研究
- 政府专职消防员(文职雇员)应聘登记表
- 23秋国家开放大学《小学语文教学研究》形考任务1-5参考答案
- 易导致患者跌倒的药品目录
- 搅拌站调度日常巡查记录表范本
- 普外科科室规章制度模板
- 初中生物七年级人体内物质的运输 单元作业设计
- 创业公司预算表格式
- 口腔助理医师考试大纲
- DLT-969-2023年变电站运行导则
- GB/T 42599-2023风能发电系统电气仿真模型验证
- TD-T 1070.1-2022 矿山生态修复技术规范 第1部分:通则
评论
0/150
提交评论