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]内容滚动 前面的话 当元素内容溢出元素尺寸范围时,会出现滚动条.但由于滚动条在各浏览器下表现不同,兼容性不好.所以,模拟滚动条也是很常见的 ...
随机推荐
- 最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目
最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目 最近一个来自重庆的客户找到走起君,客户的业务是做移动互联网支付,是微信支付收单渠道合作伙伴,数据库里存储的是支付流水和交易流水 ...
- 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...
- Asp.Net WebApi核心对象解析(下篇)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- MIP 官方发布 v1稳定版本
近期,MIP官方发布了MIP系列文件的全新v1版本,我们建议大家尽快完成升级. 一. 我是开发者,如何升级版本? 对于MIP页面开发者来说,只需替换线上引用的MIP文件为v1版本,就可以完成升级.所有 ...
- [APUE]系统数据文件与信息
一.口令文件 UNIX口令文件包含下表中的各个字段,这些字段包含在 由于历史原因,口令文件是/bin/passwd,而且是一个文本文件,每一行都包括了上表中的七个字段,字段之间用":&quo ...
- MVC如何使用开源分页插件shenniu.pager.js
最近比较忙,前期忙公司手机端接口项目,各种开发+调试+发布现在几乎上线无问题了:虽然公司项目忙不过在期间抽空做了两件个人觉得有意义的事情,一者使用aspnetcore开发了个人线上项目(要说线上其实只 ...
- UWP开发之Mvvmlight实践八:为什么事件注销处理要写在OnNavigatingFrom中
前一段开发UWP应用的时候因为系统返回按钮事件(SystemNavigationManager.GetForCurrentView().BackRequested)浪费了不少时间.现象就是在手机版的详 ...
- 【微信小程序开发】之如何获取免费ssl证书【图文步骤】
微信小程序要求所有网络请求都走ssl加密,因此我们开发服务端接口需要配置为https 这篇文章介绍一下如何 在 startssl 申请一个免费的ca证书. 1. 打开网站 https://www.s ...
- javascript 笔记!
1.通过javascript向文档中输出文本 document是javascript的内置对象,代表浏览器的文档部分 document.write("Hello Javascript&quo ...
- 关系型数据库与NoSQL数据库
关系型数据库的优缺点 优点: 可以做事务处理,从而保证了数据的一致性: 可以进行JOIN等多表查询: 由于以SQL标准化为前提,数据更新的开销很小(相同的字段基本上都只有一处). 缺点: 大量数据的写 ...