JS鼠标的拖拽原理
一、拖拽的流程动作
①鼠标按下
②鼠标移动
③鼠标松开
二、鼠标按下事件
①鼠标按下会触发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{ width: 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>
如有不正确之处欢迎大家指正