前面的话

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

原理简介

  拖拽让元素移动,是改变定位元素的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. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  2. 动画requestAnimationFrame

    前言 在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval 但是jQuery中还是采用了s ...

  3. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

  4. 微软.NET Core RC2正式发布,横跨所有平台

    .NET官方博客宣布了<Announcing .NET Core RC2 and .NET Core SDK Preview 1>,正式如期发布了.NET Core RC2, 现在可以放心 ...

  5. Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级

    Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...

  6. EF6 对多个数据库,多个DBContext的情况 进行迁移的方法。

    参见: http://stackoverflow.com/questions/21537558/multiple-db-contexts-in-the-same-db-and-application- ...

  7. [原创]java使用JDBC向MySQL数据库批次插入10W条数据测试效率

    使用JDBC连接MySQL数据库进行数据插入的时候,特别是大批量数据连续插入(100000),如何提高效率呢?在JDBC编程接口中Statement 有两个方法特别值得注意:通过使用addBatch( ...

  8. 文档对象模型DOM通俗讲解

    转自:http://www.jb51.net/article/42671.htm 在开始之前先说一点,DOM是非常容易理解的,但是大家说的太官方,让人很是难于理解,我们就用非常简单的语言翻译一遍.加深 ...

  9. 茂名石化BPM应用实践 ——业务协同及服务共享平台建设和应用

    一.茂名石化简介 茂名石化隶属于中国石油化工集团公司,创建于1955年,是国家"一五"期间156项重点项目之一.经过50多年的发展,茂名石化已成为我国生产规模最大的炼油化工企业之一 ...

  10. 【干货分享】流程DEMO-固定资产转移流程

    流程名: 固定资产转移  业务描述: 固定资产从某员工转移至另一员工,转出人与转入人必须不同  流程相关文件: 流程包.xml  流程说明: 直接导入流程包文件,即可使用本流程  表单:  流程:  ...