最近公司项目需要, 要实现类似游戏里面物品栏之间的拖放功能,网上关于拖拽的JS大部分都是只适合做单个元素的拖放(drag and drop) 找了很就也没找到满足需求的. 只好自己写一个了. BTW:鸡肯肉(jquery)UI组件倒是有drag drop 但是用起来太复杂 而且总觉得卡卡的 代码也很多 还要 JQUI core的支持.所以还是自己动手 丰衣足食.
原理:
drag功能好做 就不多说了
drop,一个drop对象的时候也好做 就是鼠标弹起时判断是否在drop对象内部 是的话就drop下来
而难点在于多个drag对象 且 多个可drop的对象的时候就麻烦了 , 因为首先要知道拖的是哪个 其次还要知道放下的时候是在哪个drop对象里. 这里我用的方法是循环 循环判断 放下的时候是在哪个drop元素上.
本人语文不好 表达可能不太清楚. 先看DEMO:
查看DEMO
代码:
//拖放插件DragDrop $.fn.Drag=function (options) { //document.body.onselectstart=function(){return false;} var defaults={ limit : window,//是否限制拖放范围 drop:false,//是否可drop noDrop:false,//是否可drop handle:false,//是否可drop finish:function () {}//拖拽完成后回调函数 } var options=$.extend(defaults,options); this.X=0;//初始位置 this.Y=0; this.dx=0;//位置差值 this.dy=0; var This=this; var ThisO=$(this);//被拖目标 var newElm;//放下目标(单个) ThisO.unbind('mousedown');//囧 Orz.. if (options.drop) { var ThatO=$(options.drop);//可放下位置(多个) ThisO.find('div').css({cursor:'move'}); var tempBox=$('<div id="tempBox" class="grid"></div>'); }else { if (options.handle) { ThisO.find(options.handle).css({cursor:'move'}); }else { ThisO.css({cursor:'move'}); } } //拖动开始 this.dragStart=function (e) { var cX=e.pageX; var cY=e.pageY; if (options.drop) { ThisO=$(this); if (ThisO.find('div').length!=1) {return}//如果没有拖动对象就返回 This.X=ThisO.find('div').offset().left; This.Y=ThisO.find('div').offset().top; tempBox.html(ThisO.html()); ThisO.html(''); $('body').append(tempBox); tempBox.css('left',This.X); tempBox.css('top',This.Y); }else { This.X=ThisO.offset().left; This.Y=ThisO.offset().top; ThisO.css({margin:0}) } This.dx=cX-This.X; This.dy=cY-This.Y; if (!options.drop) { ThisO.css({position:'absolute',left:This.X,top:This.Y}); } $(document).mousemove(This.dragMove); $(document).mouseup(This.dragStop); if ($.browser.msie) {ThisO[0].setCapture();}; return true; } //拖动中 this.dragMove=function (e) { var cX=e.pageX; var cY=e.pageY; if (options.limit) {//限制拖动范围 //容器的尺寸 var L=$(options.limit)[0].offsetLeft ? $(options.limit).offset().left : 0; var T=$(options.limit)[0].offsetTop ? $(options.limit).offset().top : 0; var R=L+$(options.limit).width(); var B=T+$(options.limit).height(); //获取拖动范围 var iLeft=cX-This.dx, iTop=cY-This.dy; //获取超出长度 var iRight=iLeft+parseInt(ThisO.outerWidth())-R, iBottom=iTop+parseInt(ThisO.outerHeight())-B; //先设置右下, 再设置左上 if(iRight > 0) iLeft -= iRight; if(iBottom > 0) iTop -= iBottom; if(L > iLeft) iLeft = L; if(T > iTop) iTop = T; if (options.drop) { tempBox.css({left:iLeft,top:iTop}) }else { ThisO.css({left : iLeft,top : iTop}) } }else { //不限制范围 if (options.drop) { tempBox.css({left:cX-This.dx,top:cY-This.dy}) }else { ThisO.css({left:cX-This.dx,top:cY-This.dy}); } }; return false; } //拖动结束 this.dragStop=function (e) { if (options.drop) { var flag=false; var cX=e.pageX; var cY=e.pageY; var oLf=ThisO.offset().left; var oRt=oLf+ThisO.width(); var oTp=ThisO.offset().top; var oBt=oTp+ThisO.height(); if (!(cX>oLf && cX<oRt && cY>oTp && cY<oBt)) {//如果不是在原位 for (var i=0; i<ThatO.length; i++) { var XL=$(ThatO[i]).offset().left+parseInt($(ThatO[i]).css('paddingLeft')); var XR=XL+$(ThatO[i]).width(); var YL=$(ThatO[i]).offset().top+parseInt($(ThatO[i]).css('paddingTop')); var YR=YL+$(ThatO[i]).height(); if (XL<cX && cX<XR && YL<cY && cY<YR) {//找到拖放目标 (如果有X个格子位置重叠 将会找到X个 newElm的值是最后一个,这是个待解决问题) newElm=$(ThatO[i]); flag=true; } } if (flag) {//交换位置 var temp=newElm.html(); newElm.html(tempBox.html()); ThisO.html(temp); tempBox.remove(); } } if (!flag) {//如果找不到拖放位置,归回原位 tempBox.css('left',This.X); tempBox.css('top',This.Y); ThisO.html(tempBox.html()); tempBox.remove(); } } $(document).unbind('mousemove'); $(document).unbind('mouseup'); options.finish(e,ThisO,newElm);//回调 if ($.browser.msie) {ThisO[0].releaseCapture();}; return false; } //绑定拖动 if (options.handle) { ThisO.find(options.handle).mousedown(This.dragStart); }else { ThisO.mousedown(This.dragStart); } }
1 Comment
老費
樓主您好,小弟在寫網頁的時候,找到您的範例,正好符合需求,在此先謝過。因小弟是jquery 的初學者,想請教一下,如果我想在拖動後對資料庫做讀寫的動作,應該將程式碼放在哪個位置?
網頁環境:php + mysql