本文详细解析利用JavaScript实现拖拽改变元素大小的原理与代码实现。通过定义识别区域判断拖拽方向,动态修改CSS样式调整宽高及位置,并针对鼠标移出边界、浏览器默认拖放行为及IE8兼容性问题进行代码优化,提供完整的交互逻辑与解决方案。
JavaScript实现拖拽改变元素大小原理与代码优化
简要概述
在基础拖拽功能之上,增加调整元素尺寸的功能。
实现原理与方向判断
实现原理分析
首先,需要为元素设定一个可操作的响应区域。当用户点击该区域时,系统识别为意图调整元素尺寸。

当鼠标点击元素边缘的特定红色区域时,程序即可识别用户的调整意图。
具体代码实现如下:
// 获取event对象,兼容性写法
var ev = ev || event;
// 鼠标按下时的位置
var mouseDownX = ev.clientX;
var mouseDownY = ev.clientY;
// 方块上下左右四个边的位置和方块的长宽
var T0 = this.offsetTop;
var B0 = this.offsetTop + this.offsetHeight;
var L0 = this.offsetLeft;
var R0 = this.offsetLeft + this.offsetWidth;
var W = this.offsetWidth;
var H = this.offsetHeight;
// 设置方块的识别范围
var areaT = T0 + 10;
var areaB = B0 - 10;
var areaL = L0 + 10;
var areaR = R0 - 10;
其中,变量分别定义了上、下、左、右四个方向的识别区域范围。
确定用户意图后,下一步是判断具体的调整方向,即确定元素应朝哪个方向扩展或收缩。
方向判断的代码实现如下:
// 判断改变方块的大小的方向
// 左
var changeL = mouseDownX < areaL;
// 右
var changeR = mouseDownX > areaR;
// 上
var changeT = mouseDownY < areaT;
// 下
var changeB = mouseDownY > areaB;
样式动态更新逻辑
最后一步是核心的样式更新,根据判断出的方向动态修改元素的宽、高及位置属性。
样式更新的代码实现如下:
//根据改变方块大小的方向不同进行大小的改变
// 左
if(changeL){
oDiv.style.width = (mouseDownX - mouseMoveX) + W + 'px';
oDiv.style.left = L0 - (mouseDownX - mouseMoveX) + 'px';
}
// 右
if(changeR){
oDiv.style.width = (mouseMoveX - mouseDownX) + W + 'px';
}
// 上
if(changeT){
oDiv.style.height = (mouseDownY - mouseMoveY) + H + 'px';
oDiv.style.top = T0 - (mouseDownY - mouseMoveY) + 'px';
}
// 下
if(changeB){
oDiv.style.height = (mouseMoveY - mouseDownY) + H +'px';
}
注意:在调整左侧或上侧边界时,必须同时更新元素的位置坐标(left/top),否则仅调整尺寸会导致元素右侧或下侧边界发生非预期的位移。
代码优化与兼容性处理
代码优化方案
优化前的原始代码如下:
var oDiv = document.getElementById('div1');
oDiv.onmousedown = function(ev){
// 获取event对象,兼容性写法
var ev = ev || event;
// 鼠标按下时的位置
var mouseDownX = ev.clientX;
var mouseDownY = ev.clientY;
// 方块上下左右四个边的位置和方块的长宽
var T0 = this.offsetTop;
var B0 = this.offsetTop + this.offsetHeight;
var L0 = this.offsetLeft;
var R0 = this.offsetLeft + this.offsetWidth;
var W = this.offsetWidth;
var H = this.offsetHeight;
// 设置方块的识别范围
var areaT = T0 + 10;
var areaB = B0 - 10;
var areaL = L0 + 10;
var areaR = R0 - 10;
// 判断改变方块的大小的方向
// 左
var changeL = mouseDownX < areaL;
// 右
var changeR = mouseDownX > areaR;
// 上
var changeT = mouseDownY < areaT;
// 下
var changeB = mouseDownY > areaB;
oDiv.onmousemove = function(ev){
var ev = ev || event;
// 鼠标移动时的鼠标位置
var mouseMoveX = ev.clientX;
var mouseMoveY = ev.clientY;
//根据改变方块大小的方向不同进行大小的改变
// 左
if(changeL){
oDiv.style.width = (mouseDownX - mouseMoveX) + W + 'px';
oDiv.style.left = L0 - (mouseDownX - mouseMoveX) + 'px';
}
// 右
if(changeR){
oDiv.style.width = (mouseMoveX - mouseDownX) + W + 'px';
}
// 上
if(changeT){
oDiv.style.height = (mouseDownY - mouseMoveY) + H + 'px';
oDiv.style.top = T0 - (mouseDownY - mouseMoveY) + 'px';
}
// 下
if(changeB){
oDiv.style.height = (mouseMoveY - mouseDownY) + H +'px';
}
// 限定范围
if(parseInt(oDiv.style.width) < 50){
oDiv.style.width = 50 + 'px';
}
if(parseInt(oDiv.style.height) < 50){
oDiv.style.height = 50 + 'px';
}
}
oDiv.onmouseup = function(){
oDiv.onmousemove = null;
}
}
上述代码主要存在两个问题:
1. 当鼠标移动速度过快移出元素区域时,拖拽调整功能会失效。
解决方案:将onmousemove和onmouseup事件监听器绑定到document对象上,而非元素本身。
2. 若元素内部包含文本,拖拽调整尺寸时可能触发浏览器原生的文本选择或拖放行为。
解决方案一:阻止浏览器的默认行为(适用于非IE8浏览器)。
在onmousedown事件处理函数中返回false。
解决方案二:使用全局捕获机制(针对IE8浏览器)。
在onmousedown事件中调用setCapture()启用全局捕获。
在onmouseup事件中调用releaseCapture()释放全局捕获。
优化后的完整代码如下:
<div id="div1">adfadsf</div>
<script type="text/javascript">
var oDiv = document.getElementById('div1');
oDiv.onmousedown = function(ev){
// 获取event对象,兼容性写法
var ev = ev || event;
// 鼠标按下时的位置
var mouseDownX = ev.clientX;
var mouseDownY = ev.clientY;
// 方块上下左右四个边的位置和方块的长宽
var T0 = this.offsetTop;
var B0 = this.offsetTop + this.offsetHeight;
var L0 = this.offsetLeft;
var R0 = this.offsetLeft + this.offsetWidth;
var W = this.offsetWidth;
var H = this.offsetHeight;
// 设置方块的识别范围
var areaT = T0 + 10;
var areaB = B0 - 10;
var areaL = L0 + 10;
var areaR = R0 - 10;
// 判断改变方块的大小的方向
// 左
var changeL = mouseDownX < areaL;
// 右
var changeR = mouseDownX > areaR;
// 上
var changeT = mouseDownY < areaT;
// 下
var changeB = mouseDownY > areaB;
// IE8 取消默认行为-设置全局捕获
if(oDiv.setCapture){
oDiv.setCapture();
}
document.onmousemove = function(ev){
var ev = ev || event;
// 鼠标移动时的鼠标位置
var mouseMoveX = ev.clientX;
var mouseMoveY = ev.clientY;
//根据改变方块大小的方向不同进行大小的改变
// 左
if(changeL){
oDiv.style.width = (mouseDownX - mouseMoveX) + W + 'px';
oDiv.style.left = L0 - (mouseDownX - mouseMoveX) + 'px';
}
// 右
if(changeR){
oDiv.style.width = (mouseMoveX - mouseDownX) + W + 'px';
}
// 上
if(changeT){
oDiv.style.height = (mouseDownY - mouseMoveY) + H + 'px';
oDiv.style.top = T0 - (mouseDownY - mouseMoveY) + 'px';
}
// 下
if(changeB){
oDiv.style.height = (mouseMoveY - mouseDownY) + H +'px';
}
// 限定范围
if(parseInt(oDiv.style.width) < 50){
oDiv.style.width = 50 + 'px';
}
if(parseInt(oDiv.style.height) < 50){
oDiv.style.height = 50 + 'px';
}
}
document.onmouseup = function(){
document.onmousemove = null;
// 释放全局捕获
if(oDiv.releaseCapture){
oDiv.releaseCapture();
}
}
return false;
}
以上内容涵盖了拖拽改变元素大小的核心逻辑与优化技巧,希望对学习前端交互开发有所帮助,欢迎继续支持本站内容。