上一周学了闭包和模块,这一周仍然是随着@波同砚,试着封装了一个拖拽模块。过程当中阅历了一些迂回,最最先我是盘算只用style.left的体式格局,然则这个须要设置position:absolute。可能对代码形成肯定影响。虽然CSS的transform会影响兼容,但这里我照样运用了这个属性的translate来完成挪动。
只用style完成的代码
话不多说,直接上代码:
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>
<div id="box"></div>
<script src="js/drag_module.js"></script>
</body>
</html>
重点!!JS
; //这个分号是为了防备其他的模块末了遗忘加分号,致使毛病。
(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。元素的拖拽就完成了。
transform和style的连系
因为手艺的生长,越来越多的装备最先支撑CSS3了,加上style的资本占用的更多,效力方面存在题目,所以我们斟酌运用transform。
浏览器的兼容写法
我们首先在函数Drag()前加上私有属性:
var transform = getTransform();
鄙人面再加上私有要领:
function getTransform() {
var transform = "",
divStyle = document.createElement('div').style,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
i = 0,
l = transformArr.length;
for (; i < l; i++) {
if (transformArr[i] in divStyle) {
return transform = transformArr[i];
}
}
return transform;
}
PS:记着createElement()这个要领,下次推断浏览器兼容时用得着!
我们还须要在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;
},
PS:之所以要推断transformValue是不是为none,是因为在初始化状况是,元素未被设置transform属性,如许正则以后的数组是找不到[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;
},
注重上面一段代码我们修正的的内容,在这里我们增加了一个推断:即当支撑transform属性的浏览器存在时,我们会用transform属性修正元素的值,把之前在getTranslate中获得的x、y赋值给pos的x、y。
在上面一段代码中,我们会依据浏览器的状况,用差别的要领取到雷同的值,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 = "",
divStyle = document.createElement('div').style,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
i = 0,
l = transformArr.length;
for (; i < l; i++) {
if (transformArr[i] in divStyle) {
return transform = transformArr[i];
}
}
return transform;
}
//暴露在外
window.Drag = Drag;
})();
new Drag('box');