我的开源框架之可拖拽功能实现
需求:
(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);