我的开源框架之可拖拽功能实现

需求:

  (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);

 

 

posted @ 2014-06-05 12:58  hjwen  Views(6570)  Comments(4Edit  收藏  举报