484 字
1 分钟
JS获取鼠标相对元素的位置
最近项目上遇到个需求,即页面上存在一个方框,按下鼠标后开始拖动,松开鼠标后停止。在这里记录一下开发心得
思路
逻辑上不难,无非就是分如下两步
- 触发目标元素的
mousedown事件时,获取鼠标相对元素的位置x、y - 在页面的
mousemove事件中,保证x、y永远不变
问题
思路理清了,主要解决点就是如何获取鼠标相对元素的位置了。
可以通过事件对象e.pageX/e.pageY来获取鼠标距离浏览器左/上的距离,然后只要获取拖拽元素距离浏览器左/上的距离,减去就可以得到所需位置了。
但这个距离怎么拿到呢?offsetLeft/offsetRight?
だめだよ、offset是相对于offsetParent的边界的位置,即最近的拥有定位的父元素或者table,td,th,body元素,而我需要获取相对于页面边界的距离,这显然是无法使用的。
getBoundingClientRect
详细参考,这里只做简单描述。
该方法通过元素调用element.getBoundingClientRect(),不需要传递参数。返回一个对象,包括了8个描述元素的属性,分别为:
- width:元素宽度
- height:元素高度
- left:元素左边界距离视窗左边界的距离
- top:元素上边界距离视窗上边界的距离
- right:元素右边界距离视窗左边界的距离
- bottom:元素下边界距离视窗上边界的距离
- x和y:官方未给描述,从数值来看和top与left值相等,什么作用我暂且蒙在崛川雷鼓里

既然这样,只需要通过如下方式就可以获取鼠标在元素里的位置
// 距离元素左侧距离e.pageX - element.getBoundingClientRect().left// 距离元素上方距离e.pageY - element.getBoundingClientRect().top需求实现(vue)
template部分
<div ref="mainRef" class="main"> <div ref="areaRef" class="area" @mousedown.prevent="areaMouseDown($event)"></div></div>js部分
export default { data() { return { areaStartMove: false, // 目标是否开始移动 mainAttr: {}, // 目标的容器定位数据 areaAttr: {} // 目标定位数据 } }, // 组件加载时注册鼠标移动和弹起事件 mounted() { document.body.addEventListener('mousemove', this.areaMouseMove) document.body.addEventListener('mouseup', this.areaMouseUp) }, // 组件卸载时注册鼠标移动和弹起事件 destroyed() { document.body.removeEventListener('mousemove', this.areaMouseMove) document.body.removeEventListener('mouseup', this.areaMouseUp) }, methods: { areaMouseDown(e) { const areaElement = e.currentTarget this.areaStartMove = true // 分别获取目标容器和目标的定位数据 this.mainAttr = this.$refs.mainRef.getBoundingClientRect() this.areaAttr = areaElement.getBoundingClientRect() // 获取鼠标距离目标左侧和上方的距离,存入目标定位数据中 this.areaAttr.clientX = e.pageX - this.areaAttr.left this.areaAttr.clientY = e.pageY - this.areaAttr.top }, areaMouseMove(e) { // 如果目标为移动状态, 再执行相关方法 if (this.areaStartMove) { const areaElement = this.$refs.areaRef // 根据固定的鼠标距离目标左侧和上方的距离,分别求得目标此时绝对定位的left和top const top = e.pageY - this.mainAttr.top - this.areaAttr.clientY const left = e.pageX - this.mainAttr.left - this.areaAttr.clientX // 获取最大left和top const maxTop = this.mainAttr.height - this.areaAttr.height const maxLeft = this.mainAttr.width - this.areaAttr.width // 赋予样式值,移动时不能超出边界 if (top <= 0) { areaElement.style.top = '0' } else if (top >= maxTop) { areaElement.style.top = maxTop + 'px' } else { areaElement.style.top = top + 'px' } if (left <= 0) { areaElement.style.left = '0' } else if (left >= maxLeft) { areaElement.style.left = maxLeft + 'px' } else { areaElement.style.left = left + 'px' } } }, // 鼠标弹起,移除目标的移动状态 areaMouseUp() { if (this.areaStartMove) { this.areaStartMove = false } } }}css部分
.main { position: relative;
.area { position: absolute; width: 100px; height: 40px; top: 0; left: 0; border: 2px dotted #ccc; border-radius: 2px; cursor: move; }}参考
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
JS获取鼠标相对元素的位置
https://marrydream.top/posts/web前端/js获取鼠标相对元素的位置/ 部分信息可能已经过时
相关文章 智能推荐