javascript動畫系列第四篇——拖拽改變元素大小


前面的話

  拖拽可以讓元素移動,也可以改變元素大小。本文將詳細介紹拖拽改變元素大小的效果實現

 

原理簡介

  拖拽讓元素移動,是改變定位元素的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>

源碼查看


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM