1. 程式人生 > >自建JQuery拖拽外掛

自建JQuery拖拽外掛

最近由於業務需要,要有拖拽將頁面上控制元件進行一個排序的調整,網上找的控制元件大多不能完美達到預期效果,就自己做了一個小外掛,也記錄一下,畢竟是第一次寫js外掛大笑

外掛程式碼:

/**
 * Created by linxz on 2018/1/8.
 */
;(function($,window,document,undefined){
    $.fn.drag = function(option){
    	var taglist=this;
    	$('body').append('<div id="insert" style="display:none;"></div>');
        var currentTag=null;
        var defaults={
        	insertbox:null,//'border:1px solid red;vertical-align: bottom;margin-left:10px;'//填充框模型的css
        	changeFilter:taglist
        };
        var settings = $.extend({}, defaults, option);
        function showInsert(){
        	if(settings.insertbox!=null){
        		$('#insert').css(settings.insertbox);
        	}
        	$('#insert').css('display','inline-block');
        }
        function hideInsert(){
        	$('#insert').hide();
        }
        //獲取dom的left位置
        function getElementLeft(element){
            var actualLeft = element.offsetLeft;
            var current = element.offsetParent;
            while (current !== null){
                actualLeft+=current.offsetLeft;
                current =current.offsetParent;
            }
            return actualLeft;
        }
        //獲取dom的top位置
        function getElementTop(element){
            var actualTop = element.offsetTop;
            var current = element.offsetParent;
            while (current !== null){
                actualTop+=current.offsetTop;
                current =current.offsetParent;
            }
            return actualTop;
        }
        /**
         * 判斷是否有遮蓋,如果有遮蓋,則返回遮蓋的dom
         */
        function iscover(JQuery){
        	var covermostdom=[];//遮蓋的dom元素
        	var lefttop={x:getElementLeft(JQuery[0]),y:getElementTop(JQuery[0])};//當前元素的左上角位置
        	var leftbottom={x:getElementLeft(JQuery[0]),y:getElementTop(JQuery[0])+JQuery.height()};//當前元素的左下角位置
        	var righttop={x:getElementLeft(JQuery[0])+JQuery.width(),y:getElementTop(JQuery[0])};//當前元素的右上角位置
        	var rightbottom={x:getElementLeft(JQuery[0])+JQuery.width(),y:getElementTop(JQuery[0])+JQuery.height()};//當前元素的右下角位置
        	$.each(settings.changeFilter,function(i,o){
        		if(o!=JQuery[0]){
        			//排除本身
        			var olefttop={x:getElementLeft(o),y:getElementTop(o)};//當前元素的左上角位置
                	var oleftbottom={x:getElementLeft(o),y:getElementTop(o)+$(o).height()};//當前元素的左下角位置
                	var orighttop={x:getElementLeft(o)+$(o).width(),y:getElementTop(o)};//當前元素的右上角位置
                	var orightbottom={x:getElementLeft(o)+$(o).width(),y:getElementTop(o)+$(o).height()};//當前元素的右下角位置
                	if((lefttop.y>=olefttop.y&&lefttop.y<=oleftbottom.y)||(leftbottom.y>=olefttop.y&&leftbottom.y<=oleftbottom.y)){
                		//Y軸相交
                		if((righttop.x>=olefttop.x&&righttop.x<=orighttop.x)||(lefttop.x>=olefttop.x&&lefttop.x<=orighttop.x)){
                			//X軸相交
                    		covermostdom.push({item:o,position:{olefttop,oleftbottom,orighttop,orightbottom}});
                    	}
                	}
        		}
        	});
        	var nearstdom=null;
        	var middlegap=null;
        	var jqueryxmiddle=(lefttop.x+righttop.x)/2;//當前元素的X軸中點
        	$.each(covermostdom,function(i,o){
        		//獲取元素的中點,判斷距離哪個元素最近
        		var currentxmiddle=(o.position.olefttop.x+o.position.orighttop.x)/2;
        		if(middlegap==null){
        			//第一次的時候先初始化中點距離
        			middlegap=Math.abs(jqueryxmiddle-currentxmiddle);
        			nearstdom=o.item;
        		}
        		if(Math.abs(jqueryxmiddle-currentxmiddle)<=middlegap){
        			middlegap=Math.abs(jqueryxmiddle-currentxmiddle);
        			nearstdom=o.item;
        		}
        	});
        	return nearstdom;
        }
        
        /**
         * 判斷元素1是在元素2的左邊還是右邊
         * 根據元素1的left座標和元素2的中點座標進行判斷,如果元素1的left在元素2中點的左邊則返回left,否則返回right
         * @param dom1 元素1,dom結點
         * @param dom2 元素2,dom結點
         */
        function isLeftOrRight(dom1,dom2){
        	x1=getElementLeft(dom1);
        	x2=getElementLeft(dom2)+($(dom2).width()/2);
        	if(x1<=x2){
        		return 'left';
        	}else{
        		return 'right';
        	}
        }
        
        function startDrag(target,event){
        	showInsert();
        	$('#insert').height(target.height());
//        	$('#insert').width(target.width());
        	target.css({position:'absolute'});
        }
        function dragging(target,event){
        	var covertarget=iscover(target);
        	if(covertarget!=null){
        		//如果有遮蓋,則進行換位,提示換位
        		if(isLeftOrRight(target[0],covertarget)=='left'){
        			$(covertarget).before($('#insert'));
        		}else{
        			$(covertarget).after($('#insert'));
        		}
        		showInsert();
        	}else{
        		//沒有遮蓋,不需要進行換位,隱藏換位提示
        		hideInsert();
        	}
        	target.css({left:event.pageX-(target.width()/2),top:event.pageY-(target.height())});
        }
        function dragEnd(target,event){
        	/*var covertarget=iscover(target);
        	if(covertarget!=null){
        		//如果有遮蓋,則進行換位
        		if(isLeftOrRight(target[0],covertarget)=='left'){
        			$(covertarget).before(target);
        		}else{
        			$(covertarget).after(target);
        		}
        	}*/
        	if($('#insert').is(':visible')){
        		//如果換位提示是顯示的,則進行換位,換位完成之後隱藏換位提示
        		$('#insert').after(target);
        		hideInsert();
        	}
        	target.css({position:'static',left:0,top:0});
        }
        $(this).mousedown(function(event){
        	if(event.button==0){//是滑鼠左鍵
        		currentTag=$(this);
                startDrag(currentTag,event);
        	}else if(event.button==2){//是滑鼠右鍵
        		//用於保留右鍵選單設定控制元件
        	}
        });
        $(document).mousemove(function(event){
        	if(currentTag!=null){
        		dragging(currentTag,event);
        	}
        });
        $(document).mouseup(function(event){
            if(currentTag!=null){
                dragEnd(currentTag,event);
            }
            currentTag=null;
        });
        return this;
    }
    })(jQuery,window,document);

呼叫方式:

var tt=$('.textDiv').closest('.ed-figure').drag({//呼叫方式:$(JQuery).drag()或者$(JQuery).drag({});可以傳入引數,有需要可以自己新增別的引數
    		insertbox:{'border':'1px solid green','vertical-align': 'bottom','margin-left':'10px'},
    		changeFilter:filterArr//$('.ed-figure')規定要拖動的控制元件可以放在哪些元素左右兩邊,可以是dom陣列,也可以是JQuery選擇器
    	});