本文详细介绍如何使用JavaScript实现简易的拖拽功能,重点解析将鼠标事件绑定至document而非元素本身的原因,以解决快速移动时的丢失问题。同时深入辨析scrollWidth、clientWidth、offsetWidth的定义差异,以及offsetX、clientX、pageX在获取鼠标位置时的具体行为与浏览器兼容性问题,提供完整的代码实例与原理说明。
简易拖拽功能概述
简易拖拽功能介绍
目录导航
- 代码实例展示
- 代码逻辑解析
- scrollWidth、clientWidth与offsetWidth的区别分析
- offsetX、clientX与pageX的辨析说明
- 源码下载链接
JavaScript 拖拽代码实现
代码实例部分
<div id="box" style="background: #334;width: 100px;height: 100px;position: absolute;cursor: move;"></div>
(function () {
var dragging = false
var boxX, boxY, mouseX, mouseY, offsetX, offsetY
var box = document.getElementById('box')
// 鼠标按下的动作
box.onmousedown = down
// 鼠标的移动动作
document.onmousemove = move
// 释放鼠标的动作
document.onmouseup = up
// 鼠标按下后的函数,e为事件对象
function down(e) {
dragging = true
// 获取元素所在的坐标
boxX = box.offsetLeft
boxY = box.offsetTop
// 获取鼠标所在的坐标
mouseX = parseInt(getMouseXY(e).x)
mouseY = parseInt(getMouseXY(e).y)
// 鼠标相对元素左和上边缘的坐标
offsetX = mouseX - boxX
offsetY = mouseY - boxY
}
// 鼠标移动调用的函数
function move(e){
if (dragging) {
// 获取移动后的元素的坐标
var x = getMouseXY(e).x - offsetX
var y = getMouseXY(e).y - offsetY
// 计算可移动位置的大小, 保证元素不会超过可移动范围
var width = document.documentElement.clientWidth - box.offsetWidth
var height = document.documentElement.clientHeight - box.offsetHeight
// min方法保证不会超过右边界,max保证不会超过左边界
x = Math.min(Math.max(0, x), width)
y = Math.min(Math.max(0, y), height)
// 给元素及时定位
box.style.left = x + 'px'
box.style.top = y + 'px'
}
}
// 释放鼠标的函数
function up(e){
dragging = false
}
// 函数用于获取鼠标的位置
function getMouseXY(e){
var x = 0, y = 0
e = e || window.event
if (e.pageX) {
x = e.pageX
y = e.pageY
} else {
x = e.clientX + document.body.scrollLeft - document.body.clientLeft
y = e.clientY + document.body.scrollTop - document.body.clientTop
}
return {
x: x,
y: y
}
}
})()
代码解析部分
在 document 对象上绑定 mousemove 和 mouseup 事件,而非直接在拖拽元素上绑定,主要是为了防止当鼠标移动速度过快导致光标超出元素范围时拖拽停止。由于 document 覆盖整个页面,将其作为事件目标可确保无论鼠标移动多快都不会脱离监听范围,从而保证拖拽的连续性。
// 鼠标按下的动作
box.onmousedown = down
// 鼠标的移动动作
document.onmousemove = move
// 释放鼠标的动作
document.onmouseup = up
HTMLElement.offsetLeft 是一个只读属性,用于返回当前元素左上角相对于其 offsetParent 节点左边界的像素偏移值。
// 获取元素所在的坐标
boxX = box.offsetLeft
boxY = box.offsetTop
通常使用 pageX 或 pageY 属性来获取鼠标位置,但 Internet Explorer 旧版本不支持这两个属性。因此,在 IE 浏览器中,需要通过计算 event.clientX 加上 document.body.scrollLeft 再减去 document.body.clientLeft 来获取准确的鼠标位置坐标。
if (e.pageX) {
x = e.pageX
y = e.pageY
} else {
x = e.clientX + document.body.scrollLeft - document.body.clientLeft
y = e.clientY + document.body.scrollTop - document.body.clientTop
}
DOM 宽度属性差异解析
scrollWidth、clientWidth 与 offsetWidth 的区别详解
基本定义说明
- scrollWidth:表示对象实际内容的宽度,计算时不包含边框(border)和滚动条的宽度。
- clientWidth:表示对象内容可视区域的宽度,同样不包含边框和滚动条的宽度。
- offsetWidth:表示对象整体的实际渲染宽度,包含内容、内边距(padding)、边框(border)以及滚动条的宽度。
情况一:元素内部无内容或内容宽度未超过可视区,此时滚动条不出现或不可用。
在此情况下,scrollWidth 等于 clientWidth,而 offsetWidth 代表元素的实际物理宽度。
情况二:元素内的内容宽度超过可视区,导致滚动条出现且可用。
在此情况下,scrollWidth 大于 clientWidth,而 offsetWidth 依然代表元素的实际物理宽度。
鼠标坐标属性行为辨析
offsetX、clientX 与 pageX 的具体辨析
offsetX 与 offsetY 说明
这两个属性指鼠标指针相对于触发事件元素左上角的偏移量。在 Chrome、Opera 和 Safari 等浏览器中,计算包含元素边框宽度;而在 Firefox 中,计算不包含边框值。
pageX 与 pageY 说明
这两个属性指鼠标位置相对于文档窗口左上角的距离,其数值不会随页面滚动条的移动而改变。
clientX 与 clientY 说明
这两个属性指鼠标位置相对于浏览器可视窗口左上角的距离,其参照点会随滚动条的滚动而动态变化。
源码下载链接
星辉的Github仓库地址
以上就是 JavaScript 实现简易拖拽功能的详细内容,更多关于相关技术细节的资料请关注本站其他文章。