文章出處
文章列表
前面的話
上一篇,我們介紹了元素拖拽的實現。但在實際應用中,常常需要為拖拽的元素限定范圍。而通過限定范圍,再增加一些輔助的措施,就可以實現磁性吸附的效果
范圍限定
如果我們限定元素只可以在可視范圍內移動,那么就需要對其進行范圍限定
首先,先要搞清楚是可視區域限定被拖拽元素
左側范圍L0 = 0
右側范圍R0 = document.documentElement.clientWidth
上側范圍T0 = 0
下側范圍B0 = document.documentElement.clientHeight
元素的上下左右四邊分別為
左側邊 L = offsetLeft
右側邊 R = offsetLeft + offsetWidth
上側邊 T = offsetTop
下側邊 B = offsetTop + offsetHeight
function limitedRange(obj,fn){ var L0 = 0; var R0 = document.documentElement.clientWidth; var T0 = 0; var B0 = document.documentElement.clientHeight; var L = obj.offsetLeft; var R = obj.offsetLeft + obj.offsetWidth; var T = obj.offsetTop; var B = obj.offsetTop + obj.offsetHeight; if(L >= L0 && R <= R0 && T >= T0 && B <= B0){ fn(obj); } }
拖拽范圍
如果將范圍限定在拖拽元素上,則需要一些改變
首先,限定條件并不是在范圍內執行什么,而是不在范圍內時,應該執行什么
由于在拖拽實現中,已經獲取了元素距離可視區域左上角的X軸和Y軸的距離,所以不需要再通過offsetLeft和offsetTop進行重新獲取
<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">測試文字</div> <script> function addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,handler,false); }else{ target.attachEvent('on'+type,function(event){ return handler.call(target,event); }); } } (function(){ var x0,y0,x1,y1,isMoving; var ele = document.getElementById('test'); var L0,R0,T0,B0,EH,EW; var mousedownHandler = function(e){ e = e || event; //獲取元素距離定位父級的x軸及y軸距離 x0 = this.offsetLeft; y0 = this.offsetTop; //獲取此時鼠標距離視口左上角的x軸及y軸距離 x1 = e.clientX; y1 = e.clientY; //按下鼠標時,表示正在運動 isMoving = true; //鼠標按下時,獲得此時的頁面區域 L0 = 0; R0 = document.documentElement.clientWidth; T0 = 0; B0 = document.documentElement.clientHeight; //鼠標按下時,獲得此時的元素寬高 EH = ele.offsetHeight; EW = ele.offsetWidth; } var mousemoveHandler = function(e){ //如果沒有觸發down事件,而直接觸發move事件,則函數直接返回 if(!isMoving){ return; } e = e || event; //獲取此時鼠標距離視口左上角的x軸及y軸距離 var x2 = e.clientX; var y2 = e.clientY; //計算此時元素應該距離視口左上角的x軸及y軸距離 var X = x0 + (x2 - x1); var Y = y0 + (y2 - y1); /******范圍限定*******/ //獲取鼠標移動時元素四邊的瞬時值 var L = X; var R = X + EW; var T = Y; var B = Y + EH; //在將X和Y賦值給left和top之前,進行范圍限定。只有在范圍內時,才進行相應的移動 //如果脫離左側范圍,則left置L0 if(L < L0){X = L0;} //如果脫離右側范圍,則left置為R0 if(R > R0){X = R0 - EW;} //如果脫離上側范圍,則top置T0 if(T < T0){Y = T0;} //如果脫離下側范圍,則top置為B0 if(B > B0){Y = B0 - EH;} //將X和Y的值賦給left和top,使元素移動到相應位置 ele.style.left = X + 'px'; ele.style.top = Y + 'px'; } var mouseupHandler = function(e){ //鼠標抬起時,表示停止運動 isMoving = false; //釋放全局捕獲 if(ele.releaseCapture){ ele.releaseCapture(); } } var preventDefaultHandler = function(e){ e = e || event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue = false; } //IE8-瀏覽器阻止默認行為 if(ele.setCapture){ ele.setCapture(); } } addEvent(ele,'mousedown',mousedownHandler); addEvent(ele,'mousedown',preventDefaultHandler); addEvent(document,'mousemove',mousemoveHandler) addEvent(document,'mouseup',mouseupHandler) })(); </script>
磁性吸附
磁性吸附只需要在范圍限定的基礎上,做一些修改即可
下列代碼中,只要元素的四邊,距離可視區域范圍的四邊小于50px,則元素將直接吸附對應的邊上
<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">測試文字</div> <script> function addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,handler,false); }else{ target.attachEvent('on'+type,function(event){ return handler.call(target,event); }); } } (function(){ var x0,y0,x1,y1,isMoving; var ele = document.getElementById('test'); var L0,R0,T0,B0,EH,EW; var mousedownHandler = function(e){ e = e || event; //獲取元素距離定位父級的x軸及y軸距離 x0 = this.offsetLeft; y0 = this.offsetTop; //獲取此時鼠標距離視口左上角的x軸及y軸距離 x1 = e.clientX; y1 = e.clientY; //按下鼠標時,表示正在運動 isMoving = true; //鼠標按下時,獲得此時的頁面區域 L0 = 0; R0 = document.documentElement.clientWidth; T0 = 0; B0 = document.documentElement.clientHeight; //鼠標按下時,獲得此時的元素寬高 EH = ele.offsetHeight; EW = ele.offsetWidth; } var mousemoveHandler = function(e){ //如果沒有觸發down事件,而直接觸發move事件,則函數直接返回 if(!isMoving){ return; } e = e || event; //獲取此時鼠標距離視口左上角的x軸及y軸距離 var x2 = e.clientX; var y2 = e.clientY; //計算此時元素應該距離視口左上角的x軸及y軸距離 var X = x0 + (x2 - x1); var Y = y0 + (y2 - y1); /******磁性吸附*******/ //獲取鼠標移動時元素四邊的瞬時值 var L = X; var R = X + EW; var T = Y; var B = Y + EH; //在將X和Y賦值給left和top之前,進行范圍限定。只有在范圍內時,才進行相應的移動 //如果到達左側的吸附范圍,則left置L0 if(L - L0 < 50){X = L0;} //如果到達右側的吸附范圍,則left置為R0 if(R0 - R < 50){X = R0 - EW;} //如果到達上側的吸附范圍,則top置T0 if(T - T0 < 50){Y = T0;} //如果到達右側的吸附范圍,則top置為B0 if(B0 - B < 50){Y = B0 - EH;} //將X和Y的值賦給left和top,使元素移動到相應位置 ele.style.left = X + 'px'; ele.style.top = Y + 'px'; } var mouseupHandler = function(e){ //鼠標抬起時,表示停止運動 isMoving = false; //釋放全局捕獲 if(ele.releaseCapture){ ele.releaseCapture(); } } var preventDefaultHandler = function(e){ e = e || event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue = false; } //IE8-瀏覽器阻止默認行為 if(ele.setCapture){ ele.setCapture(); } } addEvent(ele,'mousedown',mousedownHandler); addEvent(ele,'mousedown',preventDefaultHandler); addEvent(document,'mousemove',mousemoveHandler) addEvent(document,'mouseup',mouseupHandler) })(); </script>
文章列表
全站熱搜