题目:JavaScript 鼠标事件与键盘事件深入应用
描述: 假设你正在开发一个网页应用,该应用有一个功能是允许用户通过拖拽一个可拖拽元素(div)来改变其在页面上的位置。同时,当用户按下 Esc 键时,可拖拽元素应返回到其初始位置。请使用 JavaScript 实现以下要求:
- 当鼠标按下在可拖拽元素上时,开始拖拽。
- 当鼠标按下并移动时,可拖拽元素应跟随鼠标移动。
- 当鼠标释放时,结束拖拽并使元素保持在当前位置。
- 当用户按下 Esc 键时,可拖拽元素返回到其初始位置。
请提供 HTML、CSS 和 JavaScript 代码以实现上述功能,并考虑浏览器兼容性问题。
PS:解答这道题目需要对 JavaScript 的鼠标事件(mousedown、mousemove 和 mouseup)以及键盘事件(keydown)有深入的了解。此外,还需了解如何使用事件监听器和如何处理事件对象,以便在事件发生时执行相应的操作。同时,考虑到浏览器兼容性问题,需要了解不同浏览器中事件处理的差异。
答案
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draggable Element with Escape Reset</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="draggable" id="draggableElement">Drag me</div>
<script src="script.js"></script>
</body>
</html>
CSS代码
.draggable {
position: absolute;
width: 100px;
height: 100px;
background-color: #f44336;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
cursor: move;
}
JS代码
// 获取可拖拽元素
const draggableElement = document.getElementById('draggableElement');
// 定义拖拽状态和初始位置变量
let isDragging = false;
let initialPosition = { x: 0, y: 0 };
let mouseOffset = { x: 0, y: 0 };
// 获取元素的初始位置,用于后续的 Esc 键复位操作
const getInitialPosition = () => {
const rect = draggableElement.getBoundingClientRect();
initialPosition = { x: rect.left, y: rect.top };
};
// 鼠标按下事件处理函数
const onMouseDown = (event) => {
isDragging = true;
// 计算鼠标相对于元素的偏移量
mouseOffset.x = event.clientX - draggableElement.getBoundingClientRect().left;
mouseOffset.y = event.clientY - draggableElement.getBoundingClientRect().top;
};
// 鼠标移动事件处理函数
const onMouseMove = (event) => {
if (isDragging) {
// 计算元素新位置并应用到元素的样式上
const newX = event.clientX - mouseOffset.x;
const newY = event.clientY - mouseOffset.y;
draggableElement.style.left = newX + 'px';
draggableElement.style.top = newY + 'px';
}
};
// 鼠标释放事件处理函数
const onMouseUp = () => {
isDragging = false;
};
// 按下 Esc 键时的事件处理函数
const onEscapeKey = (event) => {
if (event.key === 'Escape' || event.keyCode === 27) {
// 将元素位置复位到初始位置
draggableElement.style.left = initialPosition.x + 'px';
draggableElement.style.top = initialPosition.y + 'px';
}
};
// 为元素添加事件监听器
draggableElement.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
document.addEventListener('keydown', onEscapeKey);
// 获取元素的初始位置
getInitialPosition();
在这个实现中,我们首先获取可拖拽元素并定义一些用于存储拖拽状态、初始位置和鼠标偏移量的变量。接下来,我们编写四个事件处理函数:onMouseDown
、onMouseMove
、onMouseUp
和 onEscapeKey
。它们分别用于处理鼠标按下、鼠标移动、鼠标释放和按下 Esc 键的事件。
在 onMouseDown
事件处理函数中,我们设置 isDragging
为 true
,并计算鼠标相对于元素的偏移量,以便在接下来的 onMouseMove
事件处理函数中正确计算元素的新位置。
在 onMouseMove
事件处理函数中,我们首先检查 isDragging
是否为 true
,然后计算元素的新位置,并将其应用到元素的样式上,从而使元素跟随鼠标移动。
在 onMouseUp
事件处理函数中,我们将 isDragging
设置为 false
,以结束拖拽操作。
在 onEscapeKey
事件处理函数中,我们检查事件对象的 key
或 keyCode
属性是否表示 Esc 键。如果是,我们将元素的位置复位到初始位置。为了兼容不同浏览器,我们同时检查 key
和 keyCode
属性。
最后,我们为可拖拽元素和整个文档添加相应的事件监听器,并在页面加载时获取元素的初始位置。
这个实现应该在大多数现代浏览器中都能良好地工作。关于优化方案,可以考虑使用 requestAnimationFrame
对 onMouseMove
事件处理函数进行节流,以提高拖拽性能。此外,为了处理触摸屏设备,还可以考虑添加对 touchstart
、touchmove
和 touchend
事件的支持。
原文链接:https://juejin.cn/post/7232239024106160187 作者:2002XiaoYu