javascript動畫系列第四篇——拖拽改變元素大小
阿新 • • 發佈:2018-12-30
前面的話
拖拽可以讓元素移動,也可以改變元素大小。本文將詳細介紹拖拽改變元素大小的效果實現
原理簡介
拖拽讓元素移動,是改變定位元素的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; //<