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 100%; 13 } 14 15 #main { 16 height: 470px; 17 470px; 18 border: 1px solid #dddddd; 19 position: relative; 20 } 21 22 .item { 23 height: 150px; 24 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() eleaseCapture(),这两个方法, 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>