javascript动画系列第四篇——拖拽改变元素大小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>
//共享mousedown事件的变量,设置为全局变量
var EW,EH,EX,EY,disL,disH;
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;}
    //如果改变元素尺寸功能开启
    if(test.clientChange){
        //处于左侧范围
        if(areaL){
            this.style.left = e.clientX - disL + px;
            this.style.width = EW + EX - e.clientX + px; 
        }
        //处于右侧范围
        if(areaR){this.style.width = EW + e.clientX - EX + px;}
        //处于上侧范围
        if(areaT){
            this.style.top = e.clientY - disH + px;
            this.style.height = EH + EY - e.clientY + px;
        }
        //处于下侧范围
        if(areaB){this.style.height = EH + e.clientY - EY + px; }                
    }
    test.onmousedown = function(e){
        e = e || event;
        //记录鼠标按下时的宽高及鼠标clienX、clientY值
        EW = this.offsetWidth;
        EH = this.offsetHeight;
        EX = e.clientX;
        EY = e.clientY;
        //记录鼠标按下位置距离元素左侧的距离
        disL = EX - L0;
        //记录鼠标按下位置距离元素上侧的距离
        disH = EY - T0;
        //开启改变元素尺寸功能
        test.clientChange = true;
    }
    test.onmouseup = function(e){
        //关闭改变元素尺寸功能
        test.clientChange = false;
    }    
}
</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>
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;}
    test.onmousedown = function(e){
        var that = this;
        e = e || event;
        //取消默认行为
        if(e.preventDefault){
            e.preventDefault();
        }
        //IE8-浏览器阻止默认行为
        if(that.setCapture){
            that.setCapture();
        }
        //记录鼠标按下时的宽高及鼠标clienX、clientY值
        var EW = this.offsetWidth;
        var EH = this.offsetHeight;
        var EX = e.clientX;
        var EY = e.clientY;
        //记录鼠标按下位置距离元素左侧的距离
        var disL = EX - L0;
        //记录鼠标按下位置距离元素上侧的距离
        var disH = EY - T0;
        document.onmousemove = function(e){
            var thatL,thatW,thatT,thatH;
            e = e || event;
            //处于左侧范围
            if(areaL){
                thatL= e.clientX - disL + px;
                thatW= EW + EX - e.clientX + px; 
            }
            //处于右侧范围
            if(areaR){thatW= EW + e.clientX - EX + px;}
            //处于上侧范围
            if(areaT){
                thatT = e.clientY - disH + px;
                thatH = EH + EY - e.clientY + px;
            }
            //处于下侧范围
            if(areaB){thatH = EH + e.clientY - EY + px;}
            //范围限定
            if(parseInt(thatW) < 60){thatW = 60px;}    
            if(parseInt(thatH) < 60){thatH = 60px;}
            //赋值
            if(thatW != undefined){that.style.width = thatW;}
            if(thatH != undefined){that.style.height = thatH;}
            if(thatT != undefined){that.style.top = thatT;}
            if(thatL != undefined){that.style.left = thatL;}            
        }
           document.onmouseup = function(e){
            //关闭改变元素尺寸功能
            document.onmousemove = null;
            //释放全局捕获
            if(that.releaseCapture){
                that.releaseCapture();
            }
        }
    }
}
</script>

源码查看

以上是关于javascript动画系列第四篇——拖拽改变元素大小的主要内容,如果未能解决你的问题,请参考以下文章

javascript动画系列第二篇——磁性吸附

深入理解表单脚本系列第四篇——选择框脚本

javascript动画系列第三篇——碰撞检测

javascript动画系列第五篇——模拟滚动条

AdvancedLocomotionSystemV第四篇 C++ 实现角色跑步旋转和原地旋转

AdvancedLocomotionSystemV第四篇 C++ 实现角色跑步旋转和原地旋转