試著封裝了一個拖曳模組。過程中經歷了一些曲折,我打算只用style.left的方式,但這個需要設定position:absolute。可能對程式碼造成一定影響。雖然CSS的transform會影響相容,但這裡我還是使用了這個屬性的translate來完成移動。
話不多說,直接上程式碼:
#html和css,這裡必須設定position,第一次寫這段程式碼的時候忘了,結果儘管JS寫對了,效果完全出不來....真是短路了
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>学习</title> <style> *{ margin: 0; padding: 0; } #box{ width: 200px; height: 200px; background: #6f6; font-size: 20px; cursor:move; position: absolute; } </style> </head> <body> <p id="box"></p> <script src="js/drag_module.js"></script> </body> </html>
; //这个分号是为了防止其他的模块最后忘记加分号,导致错误。 (function() { //构造函数,属于每一个实例 function Drag(selector) { this.elem = typeof selector == 'object' ? selector : document.getElementById(selector); //鼠标初始位置 this.startX = 0; this.startY = 0; //元素初始位置 this.sourceX = 0; this.sourceY = 0; this.init(); } //原型,共有的 Drag.prototype = { constructor: Drag, init: function() { this.setDrag(); }, //用于获取元素当前的位置信息 getPosition: function() { var that = this; var pos = {}; pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; return pos; }, //用来设置当前元素的位置 setPosition: function(pos) { this.elem.style.left = pos.x + 'px'; this.elem.style.top = pos.y + 'px'; }, //该方法用来绑定事件 setDrag: function() { var self = this; this.elem.addEventListener('mousedown', start, false); function start(event) { self.startX = event.pageX; self.startY = event.pageY; var pos = self.getPosition(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { //总体思想:鼠标距浏览器距-鼠标距元素距离 var currentX = event.pageX; //当前的鼠标x位置 var currentY = event.pageY; //当前的鼠标y位置 var distanceX = currentX - self.startX; //鼠标移动的距离x var distanceY = currentY - self.startY; //鼠标移动的距离y self.setPosition({ x: self.sourceX + distanceX, y: self.sourceY + distanceY }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); } } }; //暴露在外 window.Drag = Drag; })(); new Drag('box');
這段程式碼是比較好理解的,在一開始看波大神的程式碼時,對於translate的運用其實我沒看太明白,因為沒想到為啥要用到正則.. ....
雖然比較簡單,但我們還是要分析這段程式碼的原理:
1.自執行函式裡有一個建構函式Drag(),在建構子裡我們設定的方法和屬性時每一個建構函式實例獨有的,例如他們的位置資訊等。而在原型裡的有三個方法:分別是取得元素位置資訊的getPosition()、設定元素位置的setPosition()和綁定事件的setDrag(),這三個因為是公用的,為了節省資源,我們就放在原型裡了。
2.這段程式碼執行的原理是:當滑鼠按下時,取得元素初始位置資訊sourceX/Y、滑鼠初始位置資訊startX/Y;當滑鼠移動完成時,取得滑鼠新的位置currentX/Y,兩個滑鼠位置相減就能得到滑鼠移動的距離distanceX/Y,這同時也是元素移動的距離,然後,我們把這個值賦給元素的style.left/top。元素的拖曳就實現了。
由於技術的發展,越來越多的設備開始支援CSS3了,加上style的資源佔用的更多,效率方面存在問題,所以我們考慮使用transform。
我們先在函數Drag()前面加上私有屬性:
var transform = getTransform();
在下面再加上私有方法:
function getTransform() { var transform = "", pStyle = document.createElement('p').style, transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'], i = 0, l = transformArr.length; for (; i < l; i++) { if (transformArr[i] in pStyle) { return transform = transformArr[i]; } } return transform; }
我們還需要在getPosition()的下面加上一個函數,用同樣的形式:
getTranslate: function() { var val = {}; var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform]; if(transformValue=='none'){ val={x:0,y:0}; }else{ var transformArr = transformValue.match(/-?\d+/g); val = { x: Number(transformArr[4]), y: Number(transformArr[5]) }; } return val; },
[4][5]
的,所以我們讓val的兩個屬性為0,也就是稍後會成為的transform的translateX和translateY的值。 繼續寫程式碼。上面一段我們用來提取translate的X、Y值。看下面一段:
getPosition: function() { var that = this; var pos = {}; if(transform){ var val=this.getTranslate(); pos={ x:val.x, y:val.y }; }else{ pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; } return pos; },
在上面一段程式碼中,我們會根據瀏覽器的情況,用不同的方法取到相同的值,val的值來自getTranslate(),是我們從元素的transform中提取出來的。同樣,在下面的setPosition()中,我們也要設定if判斷。
setPosition: function(pos) { if (transform) { this.elem.style[transform] = 'translate(' + pos.x + 'px' + ',' + pos.y + 'px)'; } else { this.elem.style.left = pos.x + 'px'; this.elem.style.top = pos.y + 'px'; } },
這一段沒什麼好講的,就是用不同的形式賦值而已。
到這裡,這個模組就封裝完畢了。接下來讓我們來看看完整程式碼:
; (function() { //私有属性 var transform = getTransform(); //构造函数,属于每一个实例 function Drag(selector) { this.elem = typeof selector == 'object' ? selector : document.getElementById(selector); //鼠标初始位置 this.startX = 0; this.startY = 0; //元素初始位置 this.sourceX = 0; this.sourceY = 0; this.init(); } //原型,共有的 Drag.prototype = { constructor: Drag, init: function() { this.setDrag(); }, //用于获取元素当前的位置信息 getPosition: function() { var that = this; var pos = {}; if(transform){ var val=this.getTranslate(); pos={ x:val.x, y:val.y }; }else{ pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; } return pos; }, //获取translate值 getTranslate: function() { var val = {}; var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform]; if(transformValue=='none'){ val={x:0,y:0}; }else{ var transformArr = transformValue.match(/-?\d+/g); val = { x: Number(transformArr[4]), y: Number(transformArr[5]) }; } return val; }, //用来设置当前元素的位置 setPosition: function(pos) { if (transform) { this.elem.style[transform] = 'translate(' + pos.x + 'px' + ',' + pos.y + 'px)'; } else { this.elem.style.left = pos.x + 'px'; this.elem.style.top = pos.y + 'px'; } }, //该方法用来绑定事件 setDrag: function() { var self = this; this.elem.addEventListener('mousedown', start, false); function start(event) { self.startX = event.pageX; self.startY = event.pageY; var pos = self.getPosition(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { //总体思想:鼠标距浏览器距-鼠标距元素距离 var currentX = event.pageX; //当前的鼠标x位置 var currentY = event.pageY; //当前的鼠标y位置 var distanceX = currentX - self.startX; //鼠标移动的距离x var distanceY = currentY - self.startY; //鼠标移动的距离y self.setPosition({ x: self.sourceX + distanceX, y: self.sourceY + distanceY }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); } } }; //私有方法,用来获取transform的兼容写法 function getTransform() { var transform = "", pStyle = document.createElement('p').style, transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'], i = 0, l = transformArr.length; for (; i < l; i++) { if (transformArr[i] in pStyle) { return transform = transformArr[i]; } } return transform; } //暴露在外 window.Drag = Drag; })(); new Drag('box');
相關推薦:
javascript全域變數封裝模組實作程式碼_javascript技巧
#以上是封裝一個自己的模組實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!