需求:
(1)實現元素可拖拽
(2)自定義拖拽范圍
(3)自定義按下觸發拖拽的元素
(4)支持拖拽過程中的事件監聽
實現思路:
元素可拖拽的實現關鍵為,mousedown、mousemove、mouseup三大事件。mousedown為按下觸發拖動的事件,可以定義到元素本身或其他元素;mousemove為拖動范圍元素的事件,該事件負責重新設置拖動元素的位置屬性;mouseup為拖動范圍元素的事件,該事件主要為了釋放mousemove、mouseup事件。
為避免當拖動元素內容有較大內容時,重新繪制位置造成的性能影響,可以采用拖動空元素(代理)來實現拖動過程,當拖動結束時,再調整實際元素的位置即可。
圖例:
客戶代碼:
1 <body> 2 <div id="header" style="padding-left:100px;padding-top:10px"> 3 <h1>可拖拽說明:</h1> 4 <p>(1)讓一個元素可以拖動,可以自定義拖拽范圍(第一個被設定了position的父元素),默認是window,可以自定義拖拽時鼠標的按下區域,默認是可拖拽元素本身</p> 5 <p>(2)事件支持:鼠標按下准備拖拽;拖拽中;拖拽完成后</p> 6 <p>(3)如果拖拽范圍是window,拖拽元素html會被放置在body下面</p> 7 <p>(4)為獲得良好的拖動性能,請盡量采用代理拖動模式</p> 8 <br /> 9 <br /> 10 </div> 11 <div id="dragContainer" style="padding:10px; margin:0 auto;width:960px;height:350px;padding-top:20px; background:#cccccc;padding-left:100px"> 12 <div id="dragDiv" style="width:400px;height:200px; background:#0094ff;"> 13 <h2 id="title" style="background:#E8D379;height:35px;">標題..............</h2> 14 用戶名:<input type="text" value="hjwen" /> 15 <p>(1)簡單實用的ui,不常用,不必要的功能,不實現</p> 16 <p>(2)只支持js創建,不支持html屬性形式,盡量保持html的整潔</p> 17 </div> 18 </div> 19 <script type="text/javascript"> 20 var drag; 21 $(function () { 22 //drag = $("#dragDiv").draggable({ dragArea: 'dragContainer', mousedownObj: 'title' });//限定范圍,按標題拖動 23 drag = $("#dragDiv").draggable({ mousedownObj: 'title' });//window拖動范圍,按標題拖動 24 //drag = $("#dragDiv").draggable({ dragArea: 'dragContainer', mousedownObj: 'title',proxy:false });//非代理模式拖動 25 //默認,拖動范圍body,按元素拖動 26 //drag = $("#dragDiv").draggable({ 27 // onStart: function (params) { 28 // //console.log("onStart"+JSON.stringify(params)); 29 // }, 30 // onDraging: function (params) { 31 // //console.log("onDraging" + JSON.stringify(params)); 32 // }, 33 // onStop: function (params) { 34 // //console.log("onStop" + JSON.stringify(params)); 35 // } 36 //}); 37 }); 38 </script> 39 </body>
組件代碼:
1 /****************************************** 2 *作者:hjwen 3 *電郵:hjwen88@126.com 4 *版本:1.0 5 *版權許可:中國通用開源許可協議V1.0 6 *說明:可拖動組件定義 7 ******************************************/ 8 (function ($) { 9 /******渲染目標*******/ 10 /********拖拽: mousedown -- > mousemove --->mouseup ************/ 11 function renderHtml(target) { 12 var settings = target.data('settings'); 13 target.css("position", "absolute"); 14 settings.dragArea.css("position", "relative"); 15 var offset; 16 if (settings.isWindows) {//如果拖動范圍是window,則需要將對象放置在body下 17 offset = target.offset(); 18 target.css({ top: offset.top, left: offset.left }); 19 target.appendTo(settings.dragArea); 20 } 21 var areawith = settings.dragArea.innerWidth(); 22 var areaheight = settings.dragArea.innerHeight(); 23 var targetwidth = target.innerWidth(); 24 var targeheight = target.innerHeight(); 25 var proxy = null; 26 /*****************低版本ie鼠標捕獲特性處理**********************/ 27 var isCapture=false; 28 if (typeof settings.mousedownObj[0].setCapture != 'undefined') { 29 isCapture = true; 30 } 31 settings.mousedownObj.css("cursor", "move"); 32 settings.mousedownObj.bind("mousedown", function (e) { 33 if (isCapture) { 34 settings.mousedownObj[0].setCapture(); 35 } 36 //計算拖動范圍 37 var offset = target.position(); 38 var finalleft =target.css('left'); 39 var finaltop = target.css('top'); 40 if (settings.proxy) {//創建空代理 41 proxy = $("<div style=\"cursor:move;position: absolute; background:#C9C4F5; height: " + targeheight + "px; width:" + targetwidth + "px; opacity: 0.85;top:" + finaltop + ";left:" + finalleft + ";filter:alpha(opacity=85) \"></div>").insertAfter(target); 42 } 43 e.preventDefault(); 44 var diffX = e.clientX - offset.left; 45 var diffY = e.clientY - offset.top; 46 if (typeof settings.onStart === 'function') { 47 settings.onStart({ top: offset.top, left: offset.left }); 48 } 49 settings.dragArea.bind("mousemove", function (e) { 50 var left = e.clientX - diffX; 51 var top = e.clientY - diffY; 52 if (left < 0) { 53 left = 0; 54 } else { 55 var w =areawith - targetwidth; 56 if (left > w) 57 left = w; 58 } 59 if (top < 0) { 60 top = 0; 61 } else { 62 var h = areaheight - targeheight; 63 if (top > h) 64 top = h; 65 } 66 if (settings.proxy) { 67 finalleft = left; 68 finaltop = top; 69 proxy.css({ left: left + "px", top: top + "px" }); 70 } else { 71 target.css({ left: left + "px", top: top + "px" }); 72 } 73 if (typeof settings.onDraging === 'function') { 74 settings.onDraging({ top: top, left: left }); 75 } 76 }); 77 settings.dragArea.bind("mouseup", function (e) { 78 settings.dragArea.unbind("mousemove"); 79 settings.dragArea.unbind("mouseup"); 80 if (settings.proxy) { 81 proxy.remove(); 82 proxy = null; 83 target.css({ left: finalleft + "px", top: finaltop + "px" }); 84 } 85 if (isCapture) { 86 settings.mousedownObj[0].releaseCapture(); 87 } 88 if (typeof settings.onStop === 'function') { 89 settings.onStop({ top: finaltop, left: finalleft }); 90 } 91 }); 92 }); 93 }; 94 /************私有方法********************/ 95 /**********私有方法結束*******************/ 96 var methods = { 97 init: function (options) { 98 if (typeof options == 'undefined') 99 options = {}; 100 return this.each(function () { 101 var $this = $(this); 102 if (typeof options.dragArea != 'undefined') { 103 options.isWindows = false; 104 if (typeof options.dragArea == 'string') { 105 options.dragArea = $("#" + options.dragArea); 106 } 107 } else { 108 options.isWindows = true; 109 } 110 if (typeof options.mousedownObj == 'string') { 111 options.mousedownObj = $("#" + options.mousedownObj); 112 } 113 $.fn.draggable.defaults.mousedownObj = $this; 114 $.fn.draggable.defaults.dragArea = $(window.top.document.body); 115 var settings = $this.data('settings'); 116 if (typeof settings == 'undefined') { 117 settings = $.extend({}, $.fn.draggable.defaults, options); 118 $this.data('settings', settings); 119 } else { 120 settings = $.extend({}, settings, options); 121 } 122 //創建ui布局 123 renderHtml($this); 124 if ($.myui.isDebug) { 125 $.myui.log("jQuery.draggable init finish......"); 126 } 127 }); 128 }, 129 destroy: function (options) { 130 return $(this).each(function () { 131 var $this = $(this); 132 $this.removeData('settings'); 133 }); 134 } 135 }; 136 /***** 137 *options= { mousedownObj: null,//鼠標按下對象/id,默認是拖動對象本身 138 proxy:true,//創建一個代理拖動對象,性能較好 139 dragArea: null, //默認拖動范圍對象/Id,不設置則為最頂層window(考慮到有iframe的情況) 140 onStart:function(params){},//開始拖動 params={top:x,left:y} 141 onDraging: function (params) { },//拖動中params={top:x,left:y} 142 onStop: function (params) { }//結束拖動params={top:x,left:y} 143 } 144 *****/ 145 $.fn.draggable = function (dragArea) { 146 var method = arguments[0]; 147 if (methods[method]) { 148 method = methods[method]; 149 arguments = Array.prototype.slice.call(arguments, 1); 150 } else if (typeof (method) == 'object' || !method) { 151 if ($.myui.isDebug) { 152 $.myui.log("jQuery.draggable init....."); 153 } 154 method = methods.init; 155 } else { 156 $.error('Method ' + method + ' does not exist on jQuery.draggable'); 157 return this; 158 } 159 return method.apply(this, arguments); 160 }; 161 //默認值 162 $.fn.draggable.defaults = { 163 mousedownObj: null,//鼠標按下對象/id,默認是拖動對象本身 164 proxy:true,//創建一個代理拖動對象,性能較好 165 dragArea: null, //默認拖動范圍對象/Id,不設置則為最頂層window(考慮到有iframe的情況) 166 onStart:null,//開始拖動 167 onDraging:null,//拖動中 168 onStop: null//結束拖動 169 }; 170 })(jQuery);