接着上一篇拖拽系列1、JavaScript實現簡單的拖拽效果這一篇博客將接着對上一節實現代碼利用JS面向對象(OOP)思惟對上一節代碼進行封裝;javascript
使其模塊化、避免全局函數污染、方便後期維護和調用;寫到這裏忽然想起一句話「沒有任何一個題目是完全完成的。總還會有不少事情可作......」html
我想這句話程序開發大概也適用吧,前端開發人員老是能夠結合本身以前學到「拖拽」相關知識,不斷擴展、完善、無窮無盡.......前端
;(function(){ //do something...... })();
這樣寫的好處是避免全局變量、全局函數的污染;緣由是函數存在做用域、做用域鏈、執行上下文;分號做用是避免代碼壓縮出錯問題java
1.構造函數主要用於構造實例化的對象,每一個對象都有本身特有(私有)的屬性和方法(該屬性和方法只供當前實例化對象調用);瀏覽器
2.對象原型經過調用構造函數實例化對象對屬性與方法的實現共享模塊化
3.普通函數模塊化函數
面向對象(OOP)思惟分析拖拽:this
重複說明——理解拖拽的核心就是掌握鼠標相關事件及鼠標事件相關聯的操做流程spa
被拖拽的目標元素對象有.net
①鼠標按下時mousedown;
初始化鼠標的位置initMouseX、initMouseY;初始化目標元素位置initObjX、initObjY;鼠標按下標識isDraging
②鼠標移動時mousemove; 獲取鼠標移動時的位置、計算目標元素的移動距離、設置目標元素的距離
③鼠標離開時mouseup; 中止移動,移除目標元素事件綁定;
代碼大體結構以下
1 /* 2 * 利用OOP(面向對象) 實現拖拽代碼的封裝 3 */ 4 ;(function(){ 5 //事件處理程序 6 //elem DOM對象 eventName 事件名稱 eventType 事件類型 7 function eventHandler(elem, eventName, eventType){}; 8 //移除事件兼容處理 9 function removeEventHandler(elem, eventName, eventType){} 10 //獲取style屬性值 11 function getStyleValue(elem, property){} 12 //被拖拽構造函數 13 function Drag(selector){ 14 //elem DOM對象 15 this.elem = typeof selector === 'object' ? selector : document.getElementById(selector); 16 //元素初始化位置 17 this.initObjX = 0; 18 this.initObjY = 0; 19 //鼠標初始化位置 20 this.initMouseX = 0; 21 this.initMouseY = 0; 22 this.isDraging = false; 23 //初始化--鼠標事件操做 24 this._init(); 25 } 26 //Drag對象原型 27 Drag.prototype = { 28 constructor : Drag, 29 //初始化 30 //構造原型指回Drag 等價於==>>Drag.prototype._init = function(){} 31 _init : function(){ 32 this.setDrag(); 33 }, 34 //獲取目標元素pos位置 35 getObjPos : function(elem) {}, 36 //設置被拖動元素的位置 37 setObjPos : function (elem, pos){}, 38 //設置目標元素事件及操做流程 39 setDrag : function(){} 40 } 41 //將Drag掛到全局對象window上 42 window.Drag = Drag; 43 })();
上述較複雜思路集中在構造函數Drag建立被拖拽目標元素實例化對象,初始化設置目標元素鼠標事件及操做流程上,細節代碼以下
1 //被拖拽構造函數 2 function Drag(selector){ 3 //elem DOM對象 4 this.elem = typeof selector === 'object' ? selector : document.getElementById(selector); 5 //元素初始化位置 6 this.initObjX = 0; 7 this.initObjY = 0; 8 //鼠標初始化位置 9 this.initMouseX = 0; 10 this.initMouseY = 0; 11 this.isDraging = false; 12 //初始化--鼠標事件操做 13 this._init(); 14 } 15 //Drag對象原型 16 Drag.prototype = { 17 constructor : Drag, 18 //初始化 19 //構造原型指回Drag 等價於==>>Drag.prototype._init = function(){} 20 _init : function(){ 21 this.setDrag(); 22 }, 23 //設置目標元素事件及操做流程 24 setDrag : function(){ 25 //目標元素對象 26 var self = this; 27 var time = null; //定時器 28 function mousedown(event){ 29 event = window.event || event; 30 //鼠標按下時位置 31 this.initMouseX = event.clientX; 32 this.initMouseY = event.clientY; 33 //獲取元素初始化位置pos 34 var pos = self.getObjPos(self.elem); 35 this.initObjX = pos.x; 36 this.initObjY = pos.y; 37 //mousemove 38 time = setTimeout(function(){ //緩解移動卡頓 39 eventHandler(self.elem, mousemove, "mousemove"); 40 }, 25); 41 //mouseup 42 eventHandler(self.elem, mouseup, "mouseup"); 43 //按下標識 44 self.isDraging = true; 45 } 46 function mousemove(event){ 47 event = window.event || event; 48 if(self.isDraging){ 49 //元素移動位置 == 當前鼠標移動位置 - 鼠標按下位置 + 目標元素初始化位置 50 var moveX = event.clientX - this.initMouseX + this.initObjX; 51 var moveY = event.clientY - this.initMouseY + this.initObjY; 52 //設置拖拽元素位置 53 self.setObjPos(self.elem, { 54 x : moveX, 55 y : moveY, 56 }); 57 } 58 } 59 function mouseup(event){ 60 event = window.event || event; 61 self.isDraging = false; 62 clearTimeout(time); 63 //移除事件 64 removeEventHandler(document, mousemove, 'mousemove'); 65 removeEventHandler(document, mouseup, 'mouseup'); 66 } 67 //mousedown 68 eventHandler(this.elem, mousedown, "mousedown"); 69 } 70 }
至於設置/獲取被拖拽的目標元素就很簡單咯!
調用寫法 new Drag(elem); elem爲傳入DOM對象便可
HTML代碼
1 <style> 2 body { 3 margin: 0; 4 padding: 0; 5 position: relative; 6 } 7 .box { 8 width: 100px; 9 height: 100px; 10 background: deeppink; 11 position: absolute; 12 left: 25px; 13 top: 25px; 14 cursor: move; 15 } 16 </style> 17 <div class="box" id="box" style="position: absolute;left: 25px;top: 25px;"></div> 18 <script src="js/draging.js"></script> 19 <script type="text/javascript"> 20 window.onload = function(){ 21 new Drag(document.getElementById("box")); 22 } 23 </script>
draging.js
1 /* 2 * 利用JS面向對象OOP思想實現拖拽封裝 3 */ 4 ;(function(){ 5 //事件處理程序 6 //elem DOM對象 eventName 事件名稱 eventType 事件類型 7 function eventHandler(elem, eventName, eventType){ 8 // elem.attachEvent 兼容IE9如下事件 9 elem.addEventListener ? elem.addEventListener(eventType, eventName, false) : elem.attachEvent('on'+eventType, eventName); 10 }; 11 //移除事件兼容處理 12 function removeEventHandler(elem, eventName, eventType){ 13 elem.removeEventListener ? elem.removeEventListener(eventType, eventName) : elem.detachEvent(eventType, eventName); 14 } 15 //獲取style屬性值 16 function getStyleValue(elem, property){ 17 //getComputedStyle、currentStyle 返回CSS樣式聲明對象([object CSSStyleDeclaration]) 只讀 18 //getComputedStyle 支持IE9+以上及正常瀏覽器 19 //currentStyle 兼容IE8及IE8如下獲取目標元素style樣式 20 return window.getComputedStyle(elem,null) ? window.getComputedStyle(elem,null)[property] : elem.currentStyle[property]; 21 } 22 //被拖拽構造函數 23 function Drag(selector){ 24 //elem DOM對象 25 this.elem = typeof selector === 'object' ? selector : document.getElementById(selector); 26 //元素初始化位置 27 this.initObjX = 0; 28 this.initObjY = 0; 29 //鼠標初始化位置 30 this.initMouseX = 0; 31 this.initMouseY = 0; 32 this.isDraging = false; 33 //初始化--鼠標事件操做 34 this._init(); 35 } 36 //Drag對象原型 37 Drag.prototype = { 38 constructor : Drag, 39 //初始化 40 //構造原型指回Drag 等價於==>>Drag.prototype._init = function(){} 41 //初始化鼠標事件及鼠標操做流程 42 _init : function(){ 43 this.setDrag(); 44 }, 45 //獲取目標元素pos位置 46 getObjPos : function(elem) { 47 var pos = {x: 0, y: 0}; 48 if(getStyleValue(elem, 'position') == 'static') { 49 this.elem.style.position = 'relative'; 50 return pos; 51 } else { 52 var x = parseInt(getStyleValue(elem, 'left') ? getStyleValue(elem, 'left') : 0); 53 var y = parseInt(getStyleValue(elem, 'top') ? getStyleValue(elem, 'top') : 0); 54 return pos = { 55 x: x, 56 y: y 57 } 58 } 59 }, 60 //設置被拖動元素的位置 61 setObjPos : function (elem, pos){ 62 elem.style.position = 'absolute'; 63 elem.style.left = pos.x+'px'; 64 elem.style.top = pos.y+'px'; 65 }, 66 //設置目標元素事件及操做流程 67 setDrag : function(){ 68 //目標元素對象 69 var self = this; 70 var time = null; //定時器 71 function mousedown(event){ 72 event = window.event || event; 73 //鼠標按下時位置 74 this.initMouseX = event.clientX; 75 this.initMouseY = event.clientY; 76 //獲取元素初始化位置pos 77 var pos = self.getObjPos(self.elem); 78 this.initObjX = pos.x; 79 this.initObjY = pos.y; 80 //mousemove 81 time = setTimeout(function(){ //緩解移動卡頓 82 eventHandler(self.elem, mousemove, "mousemove"); 83 }, 25); 84 //mouseup 85 eventHandler(self.elem, mouseup, "mouseup"); 86 //按下標識 87 self.isDraging = true; 88 } 89 function mousemove(event){ 90 event = window.event || event; 91 if(self.isDraging){ 92 //元素移動位置 == 當前鼠標移動位置 - 鼠標按下位置 + 目標元素初始化位置 93 var moveX = event.clientX - this.initMouseX + this.initObjX; 94 var moveY = event.clientY - this.initMouseY + this.initObjY; 95 //設置拖拽元素位置 96 self.setObjPos(self.elem, { 97 x : moveX, 98 y : moveY, 99 }); 100 } 101 } 102 function mouseup(event){ 103 event = window.event || event; 104 self.isDraging = false; 105 clearTimeout(time); 106 //移除事件 107 removeEventHandler(document, mousemove, 'mousemove'); 108 removeEventHandler(document, mouseup, 'mouseup'); 109 } 110 //mousedown 111 eventHandler(this.elem, mousedown, "mousedown"); 112 } 113 } 114 //將Drag掛到全局對象window上 115 window.Drag = Drag; 116 })();
在線編輯代碼請點擊 http://jsrun.net/uukKp/edit