首先看一下演示效果,项目在线演示
实现思路:将元素拖动分为三部分,鼠标按下,鼠标移动,鼠标弹起,分别监听三个事件。首先是定义四个变量startX,startY,sourceX,sourceY,分别代表鼠标点击的横纵坐标和物体的横纵坐标(左上角坐标),接着定义鼠标点击的监听事件,当鼠标点击时,记录鼠标点击的坐标还有物体的坐标,然后给文档加上鼠标移动和鼠标弹起事件
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);
}
当鼠标移动时,获取鼠标移动后的坐标,用移动后的坐标减去点击时的坐标,得到移动坐标的差值,在分别加到物体的x,y坐标上;当鼠标弹起时,移除文档对象的鼠标移动和鼠标弹起监听事件
function move(event){
var currentX = event.pageX; //获取鼠标移动后的坐标
var currentY = event.pageY;
var disX = currentX - self.startX; //获取物体应该移动的距离
var disY = currentY - self.startY;
self.setPosition({ //设置新的位置
x: (self.sourceX + disX).toFixed(),
y: (self.sourceY + disY).toFixed()
})
}
function end(event){
document.removeEventListener('mousemove', move); //移除文档对象的鼠标移动和鼠标弹起监听事件
document.removeEventListener('mouseup', end);
}
为了减少回流,我在移动时使用了css3的transform属性。但在使用前我们要要判断浏览器是否能够使用,如果不能只能通过改变元素left和top值达到移动的目标
function getTransform(){ //获取style中的transform属性,如果没有则返回空字符串
var transform = '',
divStyle = document.createElement('div').style,
_transforms = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
i = 0,
len = _transforms.length;
for(;i < len; i++){
if(_transforms[i] in divStyle){
return transform = _transforms[i];
}
}
return transform;
}
setPosition: function(pos){ //设置物体坐标
if(transform){ //判断transform是否能用,能的话直接使用translate,不能的话就改变left和top的值
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';
}
}
上面只介绍了关键代码,全部源码在这 https://jsrun.net/ZEXKp/edit,这里源码用了面向对象的思想进行了封装,可以通过下面方式直接创建一个可以移动的元素
new Drag(selector) //selector可以是css选择器,如'#dragObject',还可以是document的标签实例
若有什么问题,欢迎提问