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>
javascript动画系列第四篇——拖拽改变元素大小的更多相关文章
- JavaScript动画-拖拽改变元素大小
▓▓▓▓▓▓ 大致介绍 拖拽改变元素大小是在模拟拖拽上增加了一些功能 效果:拖拽改变元素大小 ▓▓▓▓▓▓ 拖拽改变元素大小原理 首先这个方块得知道我们想要改变这个它的大小,所以我给它设定一个范围,当 ...
- jquery插件之拖拽改变元素大小
该插件乃本博客作者所写,目的在于提升作者的js能力,也给一些js菜鸟在使用插件时提供一些便利,老鸟就悠然地飞过吧. 此插件旨在实现目前较为流行的拖拽改变元素大小的效果,您可以根据自己的实际需求来设置被 ...
- jQuery拖拽改变元素大小
一个非常简单的例子,体验效果:http://keleyi.com/keleyi/phtml/jqtexiao/29.htm 以下是完整代码,保存到HTML文件打开也可以体验效果. <!DOCTY ...
- javascript面向对象系列第五篇——拖拽的实现
前面的话 在之前的博客中,拖拽的实现使用了面向过程的写法.本文将以面向对象的写法来实现拖拽 写法 <style> .test{height: 50px;width: 50px;backgr ...
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
- 深入理解javascript作用域系列第四篇
前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...
- JQuery拖拽改变元素的尺寸
"元素拖拽改变大小"其实和"元素拖拽"一个原理,只是所动态改变的对象不同而已,主要在于 top.left.width.height 的运用,相对实现起来也非常容 ...
- javascript动画系列第三篇——碰撞检测
前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...
- javascript动画系列第五篇——模拟滚动条
× 目录 [1]原理介绍 [2]数字加减 [3]元素尺寸[4]内容滚动 前面的话 当元素内容溢出元素尺寸范围时,会出现滚动条.但由于滚动条在各浏览器下表现不同,兼容性不好.所以,模拟滚动条也是很常见的 ...
随机推荐
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- 异步任务队列Celery在Django中的使用
前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...
- jQuery之ajax实现篇
jQuery的ajax方法非常好用,这么好的东西,你想拥有一个属于自己的ajax么?接下来,我们来自己做一个简单的ajax吧. 实现功能 由于jq中的ajax方法是用了内置的deferred模块,是P ...
- javascript数组查重方法总结
文章参考地址:http://blog.csdn.net/chengxuyuan20100425/article/details/8497277 题目 对下列数组去重: var arr = ['aa', ...
- DDD 领域驱动设计-两个实体的碰撞火花
上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...
- 如何理解DT将是未来IT的转型之路?
如今的IT面临着内忧外患的挑战. 一方面,企业多多少少都建立了信息化,有些企业或集团甚至会有数几十个分公司,包含直销.代理.零售以及第三方物流等多种业态.越是复杂的业务,信息化建设越困难,比如运用大量 ...
- Android 算法 关于递归和二分法的小算法
// 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1. package demo; public class Mytest { public st ...
- VS2015墙内创建ionic2 【利用nrm更换源,完美!】
STEP 1 设置cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org 一句话建立cnpm STEP 2 安装nr ...
- zookeeper集群的搭建以及hadoop ha的相关配置
1.环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 master作为active主机,data1作为standby备用机,三台机器均作为数据节点,yarn资源 ...
- Linux课堂笔记(一)
一.Linux应用领域及版本介绍. 1.服务器.嵌入式.桌面应用等. (1)在服务器领域中,需要安全和稳定,特别是越老的内核版本越安全.越稳定. (2)Linux主要分内核版和发行版. 内核版本2.6 ...