原生js拖拽实现

实现分析

  最近为了应付面试,浏览了许多js知识点,试着用原生js实现拖拽效果,鼠标拖动效果很常见,像是百度首页的登录框就是经典案例,究其原因无非就是鼠标的三个事件:mousedown、mousemove和mouseup。

原理分析

  1. 鼠标按下时即mousedown,记录mousedown值为true,此时记录下当前鼠标的坐标以及要拖动元素的坐标
  2. 鼠标按下并移动即mousemove,记录下即时的鼠标新坐标,鼠标新旧坐标相减再加上第一步得到的元素坐标即为新的拖拽元素坐标,也就是拖拽坐标跟随鼠标移动。
  3. 鼠标松开时即mouseup,把鼠标状态mousedown设为false。

    代码

    html

    1
    2
    3
    4
    5
    6
     <div id="dialog">
    <div id='drag'>
    <div id="title">我是title,拖动我试一下</div>
    <div id="content">我是content,拖动我无效</div>
    </div>
    </div>

css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 #wrapper {
position: relative;
height:500px;
width:100%;
border:1px solid red;
}

#dialog {
position: absolute;
width: 300px;
height: 200px;
padding: 5px;
top: 50px;
left: 50px;
background-color: #d9e1ed;
box-shadow: 2px 2px 2px #5c5d6c;
border-radius: 5px;
}

#drag {
border: 1px solid rgb(217, 217, 217);
background-color: white;
}

#title {
background-color: rgba(198, 232, 255, 0.43);
border-bottom: 1px solid rgb(217, 217, 217);
cursor: move;
}

#content {
padding: 5px;
height: 165px;
}

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 /**
* Created by hughdai on 16/3/30.
*/
//事件处理
var EventCtrl = {
addEvent: function (ele, type, fn) {
if (ele.addEventListener) {
ele.addEventListener(type, fn, false);
}
else {
ele.attachEvent('on' + type, fn);
}
},
removeEvent: function (ele, type, fn) {
if (ele.removeEventListener) {
ele.removeEventListener(type, fn, false);
}
else {
ele.detachEvent('on' + type, fn);
}
}
}
//获取元素样式
function getStyle(ele, style) {
if (getComputedStyle) {
return getComputedStyle(ele, false)[style];
}
else {
return ele.currentStyle[style];
}
}
function drag() {
var x = 0, y = 0, top = 0, left = 0;
var mouseDown = false;
var dialog = document.getElementById('dialog');
EventCtrl.addEvent(this, 'mousedown', function (event) {
mouseDown = true;
this.onselectstart = function () {
return false;
};
var e = event || window.event;
left = parseInt(getStyle(dialog, 'left'));//记录当前元素偏移
top = parseInt(getStyle(dialog, 'top'));
x = parseInt(e.clientX || e.x);//记录当前鼠标位置
y = parseInt(e.clientY || e.y);
})

EventCtrl.addEvent(document, 'mousemove', function (event) {
if (mouseDown) {
var e = event || window.event;
var container = document.getElementById('wrapper')
var currentX = parseInt(e.clientX || e.x);//当前鼠标位置
var currentY = parseInt(e.clientY || e.y);
var displayX = currentX - x + left;//新鼠标位置减去旧鼠标位置加上元素偏移
var displayY = currentY - y + top;
var width = container.offsetWidth - dialog.offsetWidth;
var height = container.offsetHeight - dialog.offsetHeight;
console.log('displayX:' + displayX, 'displayY:' + displayY);
//限制元素不被拖出容器范围
if (displayX < 0) {
displayX = 0
}
else if (displayX > width) {
displayX = width
}
if (displayY < 0) {
displayY = 0
}
else if (displayY > height) {
displayY = height
}
dialog.style.left = displayX + 'px';
dialog.style.top = displayY + 'px';
}
})

EventCtrl.addEvent(document, 'mouseup', function (event) {
mouseDown = false;
left = parseInt(getStyle(dialog, 'left'));
top = parseInt(getStyle(dialog, 'top'));
EventCtrl.removeEvent(document, 'mousemove', function () {

})
EventCtrl.removeEvent(document, 'mouseup', function () {

})
})
}
document.addEventListener('DOMContentLoaded', function () {
drag.call(document.getElementById('title'));
}, false)

效果

我是title,拖动我试一下
我是content,拖动我无效