一、拖拽的流程动作
①鼠标按下
②鼠标移动
③鼠标松开
二、鼠标按下事件
①鼠标按下会触发onmousedown事件
var self = this;
self.elements.addEventListener("mousedown",start,false)
}
②鼠标移动会触发onmousemove事件
document.addEventListener("mousemove",move,false)
③鼠标松开会触发onmouseup事件
document.addEventListener("mouseup",end,false)
三、实现的原理讲解
拖拽其实是通过获取鼠标移动的距离来实现的,即计算移动前的位置的坐标(x,y)与移动中的位置的坐标(x,y)差值。
当鼠标按下或鼠标移动时,都可以获取到当前鼠标的位置,即移动前的位置与移动中的位置。
那么上面①与②的代码就应该变成这样
var self = this;
self.elements.addEventListener("mousedown",start,false)
function start(event) {
//鼠标按下时的鼠标所在的X,Y坐标
self.startX = event.pageX; // srarX,startY 应该要全局,因为 鼠标移动过程需要计算鼠标按下时的坐标
self.startY = event.pageY;
//初始位置的X,Y 坐标
self.sourceX = self.getStyle("left");
self.sourceY = self.getStyle("top");
document.addEventListener("mousemove",move,false)
document.addEventListener("mouseup",end,false)
}
function move(event) {
var currentX = event.pageX;
var currentY = event.pageY;
var width = document.documentElement.clientWidth ;
var height = document.documentElement.clientHeight;
var x = (event.clientX-self.startX);
var y = (event.clientY-self.startY);
if (x < 0) {
x = 0
} else if (x > width-self.getStyle("width")){
x = width-self.getStyle("width")
}
if (y<0){
y = 0
}else if (y > height - self.getStyle("height")){
y =height- self.getStyle("height")
}
self.setPosition({
x: (x)+self.sourceX ,
y:(y)+self.sourceY
})
}
移动前与移动后坐标有了,那么计算偏移,先看下图(网络图,侵权删)

很明显移动后元素的X坐标为 鼠标移动后的X坐标 - 鼠标按下的X坐标 + 元素的初始X坐标
Y坐标为 鼠标移动后的Y坐标 - 鼠标按下的Y坐标 + 元素的初始Y坐标
把新的 X,Y 替换元素的 X,Y 就搞定了。
那么代码就应该更换为:
var self = this;
self.elements.addEventListener("mousedown",start,false)
function start(event) {
self.startX = event.pageX;
self.startY = event.pageY;
self.sourceX = self.getStyle("left");
self.sourceY = self.getStyle("top");
document.addEventListener("mousemove",move,false)
document.addEventListener("mouseup",end,false)
}
function move(event) {
var currentX = event.pageX;
var currentY = event.pageY;
var width = document.documentElement.clientWidth ;
var height = document.documentElement.clientHeight;
var x = (event.clientX-self.startX);
var y = (event.clientY-self.startY);
if (x < 0) {
x = 0
} else if (x > width-self.getStyle("width")){
x = width-self.getStyle("width")
}
if (y<0){
y = 0
}else if (y > height - self.getStyle("height")){
y =height- self.getStyle("height")
}
self.setPosition({
x: (x)+self.sourceX ,
y:(y)+self.sourceY
})
}
function end() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', end);
}
},
setPosition:function (pos) {
// console.log(pos.x,pos.y)
this.elements.style.transform = "translate(" + pos.x + "px, " + pos.y + "px)"
}
整体代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#drag{
100px;
height: 100px;
background: #333;
}
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="drag"></div>
<script>
/**
* @file: drag.html
* @method Drag
* @param {Object} option - 对象 非必传 不传回创建一个div作为拖拽的对象
* @description:
* @author:
* @date: 2019/12/14 12:31
*/
function Drag(option) {
if (typeof option === "object") {
this.elements = option.drag;
} else{
this.elements = document.createElement("div");
this.elements.style.width = "100px";
this.elements.style.height = "100px";
this.elements.style.backgroundColor = "#000";
this.elements.setAttribute("class","drag");
document.body.appendChild(this.elements)
}
this.startX = 0;
this.startY = 0;
this.sourceX = 0;
this.startY = 0;
this.init()
}
Drag.prototype = {
/*
* 初始化需要绑定事件
* */
constructor:Drag,
init:function () {
this.bindEvent();
},
/*
* 获取当前拖拽元素的距离上,下位置
* @returns {number}
* */
getStyle:function(property){
// return document.defaultView.getComputedStyle(this.elements)[property]
return this.elements.getBoundingClientRect()[property]
},
/*
*绑定拖拽的元素,移动和鼠标松开后是对document的绑定,因为移动的是整个div
*
* */
bindEvent:function () {
var self = this;
self.elements.addEventListener("mousedown",start,false)
function start(event) {
self.startX = event.pageX;
self.startY = event.pageY;
self.sourceX = self.getStyle("left");
self.sourceY = self.getStyle("top");
document.addEventListener("mousemove",move,false)
document.addEventListener("mouseup",end,false)
}
function move(event) {
var currentX = event.pageX;
var currentY = event.pageY;
var width = document.documentElement.clientWidth ;
var height = document.documentElement.clientHeight;
var x = (event.clientX-self.startX);
var y = (event.clientY-self.startY);
if (x < 0) {
x = 0
} else if (x > width-self.getStyle("width")){
x = width-self.getStyle("width")
}
if (y<0){
y = 0
}else if (y > height - self.getStyle("height")){
y =height- self.getStyle("height")
}
self.setPosition({
x: (x)+self.sourceX ,
y:(y)+self.sourceY
})
}
function end() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', end);
}
},
setPosition:function (pos) {
// console.log(pos.x,pos.y)
this.elements.style.transform = "translate(" + pos.x + "px, " + pos.y + "px)"
}
}
new Drag({
drag:document.querySelector("#drag")
})
</script>
</body>
</html>
如有不正确之处欢迎大家指正