前面的话

  拖拽可以让元素移动,也可以改变元素大小。本文将详细介绍拖拽改变元素大小的效果实现

原理简介

  拖拽让元素移动,是改变定位元素的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>

源码查看

javascript动画系列第四篇——拖拽改变元素大小的更多相关文章

  1. JavaScript动画-拖拽改变元素大小

    ▓▓▓▓▓▓ 大致介绍 拖拽改变元素大小是在模拟拖拽上增加了一些功能 效果:拖拽改变元素大小 ▓▓▓▓▓▓ 拖拽改变元素大小原理 首先这个方块得知道我们想要改变这个它的大小,所以我给它设定一个范围,当 ...

  2. jquery插件之拖拽改变元素大小

    该插件乃本博客作者所写,目的在于提升作者的js能力,也给一些js菜鸟在使用插件时提供一些便利,老鸟就悠然地飞过吧. 此插件旨在实现目前较为流行的拖拽改变元素大小的效果,您可以根据自己的实际需求来设置被 ...

  3. jQuery拖拽改变元素大小

    一个非常简单的例子,体验效果:http://keleyi.com/keleyi/phtml/jqtexiao/29.htm 以下是完整代码,保存到HTML文件打开也可以体验效果. <!DOCTY ...

  4. javascript面向对象系列第五篇——拖拽的实现

    前面的话 在之前的博客中,拖拽的实现使用了面向过程的写法.本文将以面向对象的写法来实现拖拽 写法 <style> .test{height: 50px;width: 50px;backgr ...

  5. 深入理解javascript作用域系列第四篇——块作用域

    × 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...

  6. 深入理解javascript作用域系列第四篇

    前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...

  7. JQuery拖拽改变元素的尺寸

    "元素拖拽改变大小"其实和"元素拖拽"一个原理,只是所动态改变的对象不同而已,主要在于 top.left.width.height 的运用,相对实现起来也非常容 ...

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

    前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...

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

    × 目录 [1]原理介绍 [2]数字加减 [3]元素尺寸[4]内容滚动 前面的话 当元素内容溢出元素尺寸范围时,会出现滚动条.但由于滚动条在各浏览器下表现不同,兼容性不好.所以,模拟滚动条也是很常见的 ...

随机推荐

  1. C++中的事件分发

    本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...

  2. Android性能优化之利用Rxlifecycle解决RxJava内存泄漏

    前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所有想着查找一下资料学 ...

  3. EntityFramework Core 1.1是如何创建DbContext实例的呢?

    前言 上一篇我们简单讲述了在EF Core1.1中如何进行迁移,本文我们来讲讲EF Core1.1中那些不为人知的事,细抠细节,从我做起. 显式创建DbContext实例 通过带OnConfiguri ...

  4. 谈谈一些有趣的CSS题目(六)-- 全兼容的多列均匀布局问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  5. redis集成到Springmvc中及使用实例

    redis是现在主流的缓存工具了,因为使用简单.高效且对服务器要求较小,用于大数据量下的缓存 spring也提供了对redis的支持: org.springframework.data.redis.c ...

  6. mac下安装及配置tomcat

    mac下的软件不像windows下的程序那样写注册表,对于tomcat的安装来说,在mac下是名符其实的绿色软件,具体操作如下: 1.到 apache官方主页 下载完整 tar.gz文件包.(没有专门 ...

  7. B样条基函数的定义和性质

    定义:令U={u0,u1,…,um}是一个单调不减的实数序列,即ui≤ui+1,i=0,1,…,m-1.其中,ui称为节点,U称为节点矢量,用Ni,p(u)表示第i个p次(p+1阶)B样条基函数,其定 ...

  8. 声音分贝的概念,dBSPL.dBm,dBu,dBV,dBFS

    需要做个音频的PPM表,看着一堆的音频术语真是懵了,苦苦在网上扒了几天的文档,终于有了点收获,下面关于声音的分贝做个总结. 分贝 Decibel 分贝(dB)是一个对数单位(logarithmic u ...

  9. [原]一个针对LVS的压力测试报告

    LVS 测试报告 测试计划 基本功能测试 流量压力测试 响应时间测试 配置正确性测试 灾难恢复测试 测试点 基本功能测试 客户端IP地址正确性 RealServer 访问Internet测试(包括Ip ...

  10. .NET中AOP方便之神SheepAspect

    SheepAspect 简介以及代码示列: SheepAspect是一个AOP框架为.NET平台,深受AspectJ.它静织目标组件作为一个编译后的任务(编译时把AOP代码植入). 多有特性时,可根据 ...