前面的話
拖拽可以讓元素移動,也可以改變元素大小。本文將詳細介紹拖拽改變元素大小的效果實現
原理簡介
拖拽讓元素移動,是改變定位元素的left和top值實現的。而拖拽改變元素大小,則還需要改變元素的寬高

范圍圈定
我們把改變元素大小的范圍圈定在距離相應邊10px的范圍內
左側邊界L = obj.offsetLeft + 10
右側邊界R = obj.offsetLeft + obj.offsetWidth - 10
上側邊界T = obj.offsetTop + 10
下側邊界B = obj.offsetTop + obj.offsetHeight - 10

<div id="test" style="height: 100px;width: 100px;background-color: pink;">測試文字</div> <script> test.onmousemove = function(e){ e = e || event; //元素邊界確定 var L0 = this.offsetLeft; var R0 = this.offsetLeft + this.offsetWidth; var T0 = this.offsetTop; var B0 = this.offsetTop + this.offsetHeight; //范圍邊界確定 var L = L0 + 10; var R = R0 - 10; var T = T0 + 10; var B = B0 - 10; //范圍確定 var areaL = e.clientX < L; var areaR = e.clientX > R; var areaT = e.clientY < T; var areaB = e.clientY > B; //左側范圍 if(areaL){ this.style.cursor = 'w-resize'; } //右側范圍 if(areaR){ this.style.cursor = 'e-resize'; } //上側范圍 if(areaT){ this.style.cursor = 'n-resize'; } //下側范圍 if(areaB){ this.style.cursor = 's-resize'; } //左上范圍 if(areaL && areaT){ this.style.cursor = 'nw-resize'; } //右上范圍 if(areaR && areaT){ this.style.cursor = 'ne-resize'; } //左下范圍 if(areaL && areaB){ this.style.cursor = 'sw-resize'; } //右下范圍 if(areaR && areaB){ this.style.cursor = 'se-resize'; } //中間范圍 if(!areaL && !areaR && !areaT && !areaB){ this.style.cursor = 'default'; } } </script>
大小改變
處於左側范圍時,改變元素的left和width值
處於右側范圍時,改變元素的left值
處於上側范圍時,改變元素的top和height值
處於下側范圍時,改變元素的height值
[注意]元素改變前的狀態是指按下鼠標的瞬時元素的狀態
<div id="test" style="height: 100px;width: 100px;background-color: pink;position:absolute;top:100px;left:200px;">測試文字</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,EW,EH,isChanging; var ele = document.getElementById('test'); var mousedownHandler = function(e){ e = e || event; //獲取元素距離定位父級的x軸及y軸距離 x0 = ele.offsetLeft; y0 = ele.offsetTop; //獲取此時鼠標距離視口左上角的x軸及y軸距離 x1 = e.clientX; y1 = e.clientY; //獲取此時元素的寬高 EW = ele.offsetWidth; EH = ele.offsetHeight; //按下鼠標時,表示正在改變尺寸 isChanging = true; } var mousemoveHandler = function(e){ e = e || event; //元素邊界確定 var L0 = ele.offsetLeft; var R0 = ele.offsetLeft + ele.offsetWidth; var T0 = ele.offsetTop; var B0 = ele.offsetTop + ele.offsetHeight; //范圍邊界確定 var L = L0 + 10; var R = R0 - 10; var T = T0 + 10; var B = B0 - 10; //范圍確定 var areaL = e.clientX < L; var areaR = e.clientX > R; var areaT = e.clientY < T; var areaB = e.clientY > B; //左側范圍 if(areaL){ele.style.cursor = 'w-resize';} //右側范圍 if(areaR){ele.style.cursor = 'e-resize';} //上側范圍 if(areaT){ele.style.cursor = 'n-resize';} //下側范圍 if(areaB){ele.style.cursor = 's-resize';} //左上范圍 if(areaL && areaT){ele.style.cursor = 'nw-resize';} //右上范圍 if(areaR && areaT){ele.style.cursor = 'ne-resize';} //左下范圍 if(areaL && areaB){ele.style.cursor = 'sw-resize';} //右下范圍 if(areaR && areaB){ele.style.cursor = 'se-resize';} //中間范圍 if(!areaL && !areaR && !areaT && !areaB){ele.style.cursor = 'default';} //獲取此時鼠標距離視口左上角的x軸及y軸距離 var x2 = e.clientX; var y2 = e.clientY; //如果改變元素尺寸功能開啟 if(isChanging){ //處於左側范圍 if(areaL){ ele.style.left = x0 + (x2 - x1) + 'px'; ele.style.width = EW + (x1 - x2) + 'px'; } //處於右側范圍 if(areaR){ele.style.width = EW + (x2 - x1)+ 'px';} //處於上側范圍 if(areaT){ ele.style.top = y0 + (y2 - y1) + 'px'; ele.style.height = EH + (y1 - y2) + 'px'; } //處於下側范圍 if(areaB){ele.style.height = EH + (y2 - y1) + 'px'; } } } var mouseupHandler = function(e){ //鼠標抬起時,表示停止運動 isChanging = false; } addEvent(ele,'mousedown',mousedownHandler); addEvent(ele,'mousemove',mousemoveHandler); addEvent(ele,'mouseup',mouseupHandler) })(); </script>
代碼優化
與拖拽移動元素一樣,拖拽改變元素大小也存在同樣的問題
問題一:文字及圖片具有原生的拖放行為,通過取消默認行為可解決。IE8-瀏覽器不支持,使用全局捕獲來實現IE兼容
問題二:拖放過快,鼠標移動速度快於mousemove觸發速度時,鼠標脫離元素,使后續事件無法發生。把mousemove事件加在document上,即可解決
問題三:元素大小改變需要有范圍限制
<div id="test" style="height: 100px;width: 100px;background-color: pink;position:absolute;top:100px;left:200px;">測試文字</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,EW,EH,isChanging; var ele = document.getElementById('test'); var mousedownHandler = function(e){ e = e || event; //獲取元素距離定位父級的x軸及y軸距離 x0 = ele.offsetLeft; y0 = ele.offsetTop; //獲取此時鼠標距離視口左上角的x軸及y軸距離 x1 = e.clientX; y1 = e.clientY; //獲取此時元素的寬高 EW = ele.offsetWidth; EH = ele.offsetHeight; //按下鼠標時,表示正在改變尺寸 isChanging = true; } var mousemoveHandler = function(e){ e = e || event; //元素邊界確定 var L0 = ele.offsetLeft; var R0 = ele.offsetLeft + ele.offsetWidth; var T0 = ele.offsetTop; var B0 = ele.offsetTop + ele.offsetHeight; //范圍邊界確定 var L = L0 + 10; var R = R0 - 10; var T = T0 + 10; var B = B0 - 10; //范圍確定 var areaL = e.clientX < L; var areaR = e.clientX > R; var areaT = e.clientY < T; var areaB = e.clientY > B; //左側范圍 if(areaL){ele.style.cursor = 'w-resize';} //右側范圍 if(areaR){ele.style.cursor = 'e-resize';} //上側范圍 if(areaT){ele.style.cursor = 'n-resize';} //下側范圍 if(areaB){ele.style.cursor = 's-resize';} //左上范圍 if(areaL && areaT){ele.style.cursor = 'nw-resize';} //右上范圍 if(areaR && areaT){ele.style.cursor = 'ne-resize';} //左下范圍 if(areaL && areaB){ele.style.cursor = 'sw-resize';} //右下范圍 if(areaR && areaB){ele.style.cursor = 'se-resize';} //中間范圍 if(!areaL && !areaR && !areaT && !areaB){ele.style.cursor = 'default';} //獲取此時鼠標距離視口左上角的x軸及y軸距離 var x2 = e.clientX; var y2 = e.clientY; //如果改變元素尺寸功能開啟 if(isChanging){ //處於左側范圍 if(areaL){ var eleL = x0 + (x2 - x1) + 'px'; var eleW = EW + (x1 - x2) + 'px'; } //處於右側范圍 if(areaR){var eleW = EW + (x2 - x1)+ 'px';} //處於上側范圍 if(areaT){ var eleT = y0 + (y2 - y1) + 'px'; var eleH = EH + (y1 - y2) + 'px'; } //處於下側范圍 if(areaB){var eleH = EH + (y2 - y1) + 'px'; } //范圍限定 if(parseInt(eleW) < 60){eleW = '60px';} if(parseInt(eleH) < 60){eleH = '60px';} //賦值 if(eleW != undefined){ele.style.width = eleW;} if(eleH != undefined){ele.style.height = eleH;} if(eleT != undefined){ele.style.top = eleT;} if(eleL != undefined){ele.style.left = eleL;} } } var mouseupHandler = function(e){ //鼠標抬起時,表示停止運動 isChanging = 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>