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]内容滚动 前面的话 当元素内容溢出元素尺寸范围时,会出现滚动条.但由于滚动条在各浏览器下表现不同,兼容性不好.所以,模拟滚动条也是很常见的 ...
随机推荐
- Fis3的前端工程化之路[三大特性篇之声明依赖]
Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...
- 如何用百度MIP快速搭建体验友好的移动页面
在读这篇文章之前,请确定你已经了解MIP定义及加速原理.如果不确定的话,可以到MIP官网了解. 改造前期准备和注意事项: 你可以选择直接将原先的移动站点直接改成MIP站,也可以单独再做一套MIP站点与 ...
- 在ASP.NET Core中使用百度在线编辑器UEditor
在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...
- 【微框架】之一:从零开始,轻松搞定SpringCloud微框架系列--开山篇(spring boot 小demo)
Spring顶级框架有众多,那么接下的篇幅,我将重点讲解SpringCloud微框架的实现 Spring 顶级项目,包含众多,我们重点学习一下,SpringCloud项目以及SpringBoot项目 ...
- 23种设计模式--代理模式-Proxy
一.代理模式的介绍 代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到 ...
- 8、Struts2 运行流程分析
1.流程分析: 请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 ...
- Newtonsoft.Json设置类的属性不序列化
参考页面: http://www.yuanjiaocheng.net/webapi/parameter-binding.html http://www.yuanjiaocheng.net/webapi ...
- js闭包for循环总是只执行最后一个值得解决方法
<style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...
- javascript高性能编程-算法和流程控制
代码整体结构是执行速度的决定因素之一. 代码量少不一定运行速度快, 代码量多也不一定运行速度慢. 性能损失与代码组织方式和具体问题解决办法直接相关. 倒序循环可以提高性能,如: ...
- MySQL: Fabric 搭建 HA
搭建好Fabric之后,就可以在它的基础上创建HA Group. Shard Group.HA+Shard Group等.这里来说明一下如何快速的搭建HA环境. Fabric 192.168.2.23 ...