1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>拖拽</title>
8 <style>
9 html,
10 body {
11 height: 100%;
12 width: 100%;
13 }
14
15 #main {
16 height: 470px;
17 width: 470px;
18 border: 1px solid #dddddd;
19 position: relative;
20 }
21
22 .item {
23 height: 150px;
24 width: 150px;
25 border: 1px solid #cccccc;
26 /* margin:10px 0 10px 10px; */
27 position: absolute;
28 display: flex;
29 justify-content: center;
30 align-items: center;
31 font-size: 30px;
32 font-weight: 900;
33 }
34
35 .item1 {
36 background-color: aqua;
37 left: 0;
38 top: 0;
39 }
40
41 .item2 {
42 background-color: red;
43 left: 160px;
44 top: 0;
45 }
46
47 .item3 {
48 background-color: blanchedalmond;
49 left: 320px;
50 top: 0
51 }
52
53 .item4 {
54 background-color: yellowgreen;
55 left: 0;
56 top: 160px;
57 }
58
59 .item5 {
60 background-color: gold;
61 left: 160px;
62 top: 160px;
63 }
64
65 .item6 {
66 background-color: blueviolet;
67 left: 320px;
68 top: 160px;
69 }
70
71 .item7 {
72 background-color: thistle;
73 left: 0;
74 top: 320px;
75 }
76
77 .item8 {
78 background-color: salmon;
79 left: 160px;
80 top: 320px;
81 }
82
83 .item9 {
84 background-color: sienna;
85 left: 320px;
86 top: 320px;
87 }
88 </style>
89 </head>
90
91 <body>
92 <div id="main">
93 <div class="item item1">
94 1
95 </div>
96 <div class="item item2">
97 2
98 </div>
99 <div class="item item3">
100 3
101 </div>
102 <div class="item item4">
103 4
104 </div>
105 <div class="item item5">
106 5
107 </div>
108 <div class="item item6">
109 6
110 </div>
111 <div class="item item7">
112 7
113 </div>
114 <div class="item item8">
115 8
116 </div>
117 <div class="item item9">
118 9
119 </div>
120 </div>
121 </body>
122 <script type="text/javascript">
123 window.onload = function () {
124 let domMian = document.getElementById('main')
125 let mainLeft = domMian.offsetWidth
126 let mianTop = domMian.offsetHeight
127 let divItem = document.getElementsByClassName('item')
128 let newLeft, newTop, oldLeft, oldTop
129 let index = 0
130 var arr = []
131 for (let i = 0; i < divItem.length; i++) {
132 divItem[i].onmousedown = function (e) {
133 //每次都要去重新计算arr
134 arr=[]
135 for (let j = 0; j < divItem.length; j++) {
136 //左 上 右 下
137 arr.push([divItem[j].offsetLeft, divItem[j].offsetTop, divItem[j].offsetWidth + divItem[j].offsetLeft, divItem[j].offsetHeight + divItem[j].offsetTop])
138 }
139 index = i
140 var e = e || window.event; //兼容ie浏览器
141 oldLeft = divItem[i].offsetLeft
142 oldTop = divItem[i].offsetTop
143 var diffX = e.clientX - divItem[i].offsetLeft; //鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
144 var diffY = e.clientY - divItem[i].offsetTop;
145 divItem[i].style.zIndex = 99
146 /*低版本ie bug:物体被拖出浏览器可是窗口外部时,还会出现滚动条,
147 解决方法是采用ie浏览器独有的2个方法setCapture()\releaseCapture(),这两个方法,
148 可以让鼠标滑动到浏览器外部也可以捕获到事件,而我们的bug就是当鼠标移出浏览器的时候,
149 限制超过的功能就失效了。用这个方法,即可解决这个问题。注:这两个方法用于onmousedown和onmouseup中*/
150 if (typeof divItem[i].setCapture != 'undefined') {
151 divItem[i].setCapture();
152 }
153 document.onmousemove = function (e) {
154 var e = e || window.event; //兼容ie浏览器
155 var left = e.clientX - diffX;
156 var top = e.clientY - diffY;
157 //控制拖拽物体的范围只能在main元素视窗内,不允许出现滚动条
158 if (left < 0) {
159 left = 0;
160 } else if (left > mainLeft - divItem[i].offsetWidth) {
161 left = mainLeft - divItem[i].offsetWidth;
162 }
163 if (top < 0) {
164 top = 0;
165 } else if (top > mianTop - divItem[i].offsetHeight) {
166 top = mianTop - divItem[i].offsetHeight
167 }
168
169 //移动时重新得到物体的距离,解决拖动时出现晃动的现象
170 divItem[i].style.left = left + 'px';
171 divItem[i].style.top = top + 'px';
172 newLeft = left
173 newTop = top
174 };
175 document.onmouseup = function (e) { //当鼠标弹起来的时候不再移动
176 this.onmousemove = null;
177 this.onmouseup = null; //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
178 let newArr = []
179 var newIndex = 0
180 // @碰撞原理
181 // 主动元素 A 被动元素 B
182 // A.top < B.bottom 3 &&
183 // A.left < B.right 2&&
184 // A.right > B.left 0 &&
185 // A.bottom > B.top 1
186 //左 上 右 下 记录碰撞元素的个数
187 for (let k = 0; k < arr.length; k++) {
188 if (divItem[i].offsetTop < arr[k][3] && divItem[i].offsetLeft < arr[k][2] && newLeft + divItem[i].offsetWidth > arr[k][0] && newTop + divItem[i].offsetHeight > arr[k][1]) {
189 let newVal = {
190 'index': k,
191 'value': Math.abs(arr[k][0] - newLeft + arr[k][1] - newTop)
192 }
193 newArr.push(newVal)
194 }
195 }
196 let minIndex = newArr[0].value
197 /**
198 * @>= 是以免出现相等的情况
199 */
200 for (let k = 0; k < newArr.length; k++) {
201 if (minIndex >= newArr[k].value) {
202 newIndex = newArr[k].index
203 }
204 }
205 divItem[i].style.left = divItem[newIndex].offsetLeft + 'px'
206 divItem[i].style.top = divItem[newIndex].offsetTop + 'px'
207 divItem[newIndex].style.left = oldLeft + 'px'
208 divItem[newIndex].style.top = oldTop + 'px'
209 divItem[i].style.zIndex = 0
210 //修复低版本ie bug
211 if (typeof divItem[i].releaseCapture != 'undefined') {
212 divItem[i].releaseCapture();
213 }
214 }
215 };
216 }
217 }
218 </script>
219
220 </html>