马黑PHP整站系统

实现元素的拖曳和点击两种功能操作互不干扰

位置: 首页 > 前端三套件[ 发布时间: 2024.9.7  作者: 马黑  阅读: 156 ]

当一个元素同时存在拖曳和点击两种交互功能,如果使用 drag* 实现拖曳,那将不存在任何问题,因为 drag* 事件是在“隔离”的状态下运行,事件发生时不会触发其他常规操作,包括元素上的文本也不会被误选中。但若使用 mouse* 事件实现,问题就来了,移动元素结束时,元素的点击事件也会被同时触发,本文讨论如何处理这类冲突。

我们首先需要使用 mousedown 和 mouseup 事件替代 click 事件,因为 click 事件实际上可以分解为 mousedown 和 mouseup 两个事件。mousedown 事件发生时记下当前的时间,mouseup 事件发生时用现在的时间减去刚才的时间,若时间差距超过200毫秒,判为是单击事件,反之,判为拖曳事件,这样拖曳和点击就可以各司其事、互不干扰。

以下代码,子元素被点击会变色,拖曳它会在父元素范围内移动,两个功能不会混淆:

拖曳&点击

代码:

<style>
#pa {
	margin: 30px auto;
	width: 600px;
	height: 300px;
	border: 1px solid gray;
	box-sizing: border-box;
	position: relative;
}
#son {
	position: absolute;
	width: 100px;
	height: 50px;
	font: normal 14px / 50px sans-serif;
	text-align: center;
	user-select: none;
	cursor: pointer;
	background: lightblue;
}
</style>

<div id="pa">
	<div id="son">拖曳&点击</div>
</div>

<script>
var curtime = 0, draggable = false;
var offsetx = son.offsetWidth / 2, offsety = son.offsetHeight / 2;

son.onmousedown = (e) => {
	if(e.button != 0) return;
	curtime = new Date().getTime();
	draggable = true;
};

son.onmouseup = (e) => {
	if(e.button != 0) return;
	curtime = new Date().getTime() - curtime;
	if(curtime < 200) son.style.background = `#${Math.random().toString(16).substring(2,8)}`;
	curtime = 0;
};

pa.onmousemove = (e) => {
	if(!draggable) return;
	var rt = pa.getBoundingClientRect();
	let left = e.clientX - rt.left - offsetx, top = e.clientY - rt.top - offsety;
	if(left < 0) left = 0;
	if(top < 0) top = 0;
	if(left > rt.width - offsetx * 2) left = rt.width - offsetx * 2;
	if(top > rt.height - offsety * 2) top = rt.height - offsety * 2;
	son.style.cssText += `left: ${left}px; top: ${top}px;`;
};

document.onmouseup = () => draggable = false;
</script>

前一篇: 径向渐变背景演示
下一篇: svg子元素绕自身中心点运动的实现方法

发表评论:

       

评论列表 [1条]

#1 | 悄然 于 2024-9-7 16:20 发布: 这个可以用200毫秒来判断是点击还是拖动,好智能啊。。

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com