1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 16 <style> 17 /* Unable to preventDefault inside passive event listener due to target being treated as passive */ 18 * { touch-action: none; } 19 body,ul,li{margin:0;padding:0;} 20 ul{list-style: none;} 21 body{font:13px/1.5 Tahoma;100%;height:100%} 22 html{100%;height:100%} 23 #box{position:relative;100%;height:100%;} 24 #box li{float:left;100%;height:50px;overflow:hidden;background: #ccc;border:2px solid #999999;} 25 #box li.hig{100%;height:50px;overflow:hidden;border:2px dashed blue;} 26 </style> 27 </head> 28 <body> 29 <ul id="box"></ul> 30 <script> 31 let zIndex = 1 32 window.onload = function() { 33 let oBox = document.getElementById("box") 34 let aLi = oBox.getElementsByTagName("li") 35 let aPos = [] 36 let aData = [] 37 for (let i = 0; i < 6; i++){ 38 aData.push(i+1) 39 } 40 //插入结构 41 let oFragment = document.createDocumentFragment() 42 for (let i = 0; i < aData.length; i++) { 43 let oLi = document.createElement("li") 44 oLi.innerHTML = i+1 45 oFragment.appendChild(oLi) 46 } 47 oBox.appendChild(oFragment) 48 //布局转换 49 for (let i = 0; i < aLi.length; i++) { 50 aLi[i].index = i 51 aLi[i].style.top = Math.ceil(aLi[i].offsetTop) + "px" 52 aLi[i].style.left = Math.ceil(aLi[i].offsetLeft) + "px" 53 aLi[i].style.margin = "0 5px 5px 0" 54 aPos.push({ 55 "left": aLi[i].offsetLeft, 56 "top": aLi[i].offsetTop 57 }) 58 } 59 for (let i = 0; i < aLi.length; i++) { 60 aLi[i].style.position = "absolute" 61 drag(aLi[i]) 62 } 63 64 //拖拽函数 65 function drag(obj, handle) { 66 let newHandle = handle || obj 67 newHandle.style.cursor = "move" 68 newHandle.onmousedown = newHandle.ontouchstart = function(evt) { 69 let event = evt || window.event 70 let disX,disY 71 if(event.type=='touchstart'){ 72 let touch = event.touches[0] 73 disX = Number(touch.pageX) - this.offsetLeft 74 disY = Number(touch.pageY) - this.offsetTop 75 }else{ 76 disX = event.clientX - this.offsetLeft 77 disY = event.clientY - this.offsetTop 78 } 79 let oNear = null 80 obj.style.zIndex = zIndex++ 81 document.onmousemove = document.ontouchmove = function(evt) { 82 let event = evt || window.event 83 let iL,iT 84 if(event.type=='touchmove'){ 85 let touch = event.touches[0] 86 iL = Number(touch.pageX) - disX 87 iT = Number(touch.pageY) - disY 88 }else{ 89 iL = event.clientX - disX 90 iT = event.clientY - disY 91 } 92 93 let maxL = obj.parentNode.clientWidth - obj.offsetWidth 94 let maxT = obj.parentNode.clientHeight - obj.offsetHeight 95 96 iL < 0 && (iL = 0) 97 iT < 0 && (iT = 0) 98 iL > maxL && (iL = maxL) 99 iT > maxT && (iT = maxT) 100 obj.style.left = Math.ceil(iL) + "px" 101 obj.style.top = Math.ceil(iT) + "px" 102 103 for (i = 0; i < aLi.length; i++){ 104 aLi[i].className = "" 105 } 106 107 oNear = findNearest(obj) 108 109 oNear && (oNear.className = "hig") 110 111 return false 112 } 113 document.onmouseup = document.ontouchend = function() { 114 document.onmousemove = document.ontouchmove = null 115 document.onmouseup = document.ontouchend = null 116 if (oNear) { 117 let tIndex = obj.index 118 obj.index = oNear.index 119 oNear.index = tIndex 120 startMove(obj, aPos[obj.index]) 121 startMove(oNear, aPos[oNear.index], function() {}) 122 oNear.className = "" 123 let data = [Number(obj.index)+1,Number(oNear.index)+1] 124 let minNumber = Math.min.apply(Math,data) 125 let maxNumber = Math.max.apply(Math,data) 126 changeArraryElement(aData,minNumber,maxNumber) 127 console.log('data之后',aData) 128 } else { 129 startMove(obj, aPos[obj.index]) 130 } 131 newHandle.releaseCapture && newHandle.releaseCapture() 132 // console.log('aData',aData) 133 // console.log('aPos',aPos) 134 } 135 this.setCapture && this.setCapture() 136 return false 137 } 138 } 139 140 //找出相遇点中最近的元素 141 function findNearest(obj) { 142 let filterLi = [] 143 let aDistance = [] 144 for (i = 0; i < aLi.length; i++) aLi[i] != obj && (isButt(obj, aLi[i]) && (aDistance.push(getDistance(obj, aLi[i])), filterLi.push(aLi[i]))) 145 let minNum = Number.MAX_VALUE 146 let minLi = null 147 for (i = 0; i < aDistance.length; i++) aDistance[i] < minNum && (minNum = aDistance[i], minLi = filterLi[i]) 148 return minLi 149 } 150 } 151 152 //求两点之间的距离 153 function getDistance(obj1, obj2) { 154 let a = (obj1.offsetLeft + obj1.offsetWidth / 2) - (obj2.offsetLeft + obj2.offsetWidth / 2) 155 let b = (obj1.offsetTop + obj1.offsetHeight / 2) - (obj2.offsetTop + obj2.offsetHeight / 2) 156 return Math.sqrt(a * a + b * b) 157 } 158 159 //碰撞检测 160 function isButt(obj1, obj2) { 161 let l1 = obj1.offsetLeft 162 let t1 = obj1.offsetTop 163 let r1 = obj1.offsetLeft + obj1.offsetWidth 164 let b1 = obj1.offsetTop + obj1.offsetHeight 165 166 let l2 = obj2.offsetLeft 167 let t2 = obj2.offsetTop 168 let r2 = obj2.offsetLeft + obj2.offsetWidth 169 let b2 = obj2.offsetTop + obj2.offsetHeight 170 171 return !(r1 < l2 || b1 < t2 || r2 < l1 || b2 < t1) 172 } 173 174 //获取最终样式 175 function getStyle(obj, attr) { 176 return parseFloat(obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, null)[attr]) 177 } 178 179 //运动框架 180 function startMove(obj, pos, onEnd) { 181 clearInterval(obj.timer) 182 obj.timer = setInterval(function() { 183 doMove(obj, pos, onEnd) 184 }, 30) 185 } 186 187 function doMove(obj, pos, onEnd) { 188 let iCurL = getStyle(obj, "left") 189 let iCurT = getStyle(obj, "top") 190 let iSpeedL = (pos.left - iCurL) / 5 191 let iSpeedT = (pos.top - iCurT) / 5 192 iSpeedL = iSpeedL > 0 ? Math.ceil(iSpeedL) : Math.floor(iSpeedL) 193 iSpeedT = iSpeedT > 0 ? Math.ceil(iSpeedT) : Math.floor(iSpeedT) 194 if (pos.left == iCurL && pos.top == iCurT) { 195 clearInterval(obj.timer) 196 onEnd && onEnd() 197 } else { 198 obj.style.left = Math.ceil(iCurL + iSpeedL) + "px" 199 obj.style.top = Math.ceil(iCurT + iSpeedT) + "px" 200 } 201 } 202 203 //交换第几个元素的数组操作,注意:x>y 204 function changeArraryElement(arr1,x1,y1){ 205 let arr = arr1 206 let x = x1, y = y1 207 arr.splice(x - 1, 1, ...arr.splice(y - 1, 1, arr[x - 1])) 208 return arr 209 } 210 </script> 211 </body> 212 </html>