本文详解JavaScript实现拖拽效果的完整流程,涵盖鼠标按下、移动与抬起的事件绑定逻辑。针对IE低版本浏览器默认行为冲突,介绍setCapture全局捕获方案。同时解析可视区域边界限制及基于坐标临界值的物体碰撞检测算法,提供核心代码逻辑与实现细节。
本文分享利用JavaScript实现拖拽交互的具体代码示例,供读者参考学习。
1.1 拖拽的基本效果
实现思路如下:
当鼠标在目标元素上按下时,触发移动准备动作(事件绑定至该元素)。
鼠标在页面上移动时,目标元素跟随鼠标位置进行位移(事件绑定至页面)。
当鼠标抬起时,目标元素停止移动(事件绑定至页面)。
var o = document.querySelector('div');
//鼠标按下
o.onmousedown = function (e) {
//鼠标相对于盒子的位置
var offsetX = e.clientX - o.offsetLeft;
var offsetY = e.clientY - o.offsetTop;
//鼠标移动
document.onmousemove = function (e) {
o.style.left = e.clientX - offsetX + "px";
o.style.top = e.clientY - offsetY + "px";
}
//鼠标抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
1.2 拖拽中可能遇到的问题
若元素内部包含文本或图片,浏览器默认允许拖拽这些媒体内容,导致交互冲突。通常可通过设置return false来拦截默认行为,但在低版本IE浏览器中此方法无效。此时,可采用全局捕获机制来解决IE兼容性问题。
1.2.1 全局捕获
全局捕获机制仅适用于低版本IE浏览器。
<button>btn1</button>
<button>btn2</button>
<script>
var bts = document.querySelectorAll('button')
bts[0].onclick = function () {
console.log(1);
}
bts[1].onclick = function () {
console.log(2);
}
// bts[0].setCapture() //添加全局捕获
// bts[0].releaseCapture() ;//释放全局捕获
</script>
一旦为指定节点启用全局捕获,页面中其他元素将不再触发同类事件。
1.2.2 完整版的拖拽实现
var o = document.querySelector('div');
//鼠标按下
o.onmousedown = function (e) {
if (o.setCapture) { //IE低版本
o.setCapture()
}
e = e || window.event
//鼠标相对于盒子的位置
var offsetX = e.clientX - o.offsetLeft;
var offsetY = e.clientY - o.offsetTop;
//鼠标移动
document.onmousemove = function (e) {
e = e || window.event
o.style.left = e.clientX - offsetX + "px";
o.style.top = e.clientY - offsetY + "px";
}
//鼠标抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
if (o.releaseCapture) {
o.releaseCapture();//释放全局捕获
}
}
return false;//标准浏览器的默认行为
}
1.3 拖拽边界限制
可视区域宽度获取方式:
可视区域高度获取方式:
//屏幕的高度
// var h=document.documentElement.clientHeight
// var w=document.documentElement.clientWidth;
// console.log(h,w);
逻辑分析如下:
元素最大left值等于可视区域宽度减去元素自身宽度。
元素最小left值为0。
元素最小top值为0。
元素最大top值等于可视区域高度减去元素自身高度。
1.4 碰撞检测
碰撞检测的核心在于确定坐标临界值。
将两个物体的四条边分别标记为:L1, T1, R1, B1 和 L2, T2, R2, B2。
若满足 L1 > R2 或 T1 > B2 或 R1 < L2 或 B1 < T2,则判定为未发生碰撞。
<div class="one">
</div>
<div class="two"></div>
<script>
var o = document.querySelector('.one');
var ox = document.querySelector('.two');
//鼠标按下
o.onmousedown = function (e) {
if (o.setCapture) { //IE低版本
o.setCapture()
}
e = e || window.event
//鼠标相对于盒子的位置
var offsetX = e.clientX - o.offsetLeft;
var offsetY = e.clientY - o.offsetTop;
//计算最大左边距和上边距(边界)
var maxLeft = document.documentElement.clientWidth - this.offsetWidth;
var maxTop = document.documentElement.clientHeight - this.offsetHeight;
//碰撞
var L2 = ox.offsetLeft;
var T2 = ox.offsetTop;
var R2 = L2 + ox.offsetWidth;
var B2 = T2 + ox.offsetHeight
//鼠标移动
document.onmousemove = function (e) {
e = e || window.event
var x = e.clientX - offsetX;
var y = e.clientY - offsetY;
//计算边界
if (x <= 0) x = 0
if (y <= 0) y = 0
if (x >= maxLeft) x = maxLeft;
if (y >= maxTop) y = maxTop;
o.style.left = x + "px";
o.style.top = y + "px";
//计算碰撞
var L1 = o.offsetLeft;
var T1 = o.offsetTop;
var R1 = L1 + o.offsetWidth;
var B1 = T1 + o.offsetHeight;
if (L1 > R2 || T1 > B2 || R1 < L2 || B1 < T2) { //不碰撞
ox.style.backgroundColor = "blue"
} else {
ox.style.backgroundColor = "orange"
}
}
//鼠标抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
if (o.releaseCapture) {
o.releaseCapture();//释放全局捕获
}
}
return false;//标准浏览器的默认行为
}
</script>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。