javascript - 我应该监听哪些事件来隐藏 JavaScript 中的自定义上下文菜单
问题描述
我想知道我应该听哪些事件来隐藏我的自定义上下文菜单,这是一个<div>
从事件处理程序中显示的元素oncontextmenu
,就像在本机中一样。
解决方案
有多个操作可以关闭本机上下文菜单:
点击外部:监听 a
document.onmousedown
并且,为了防止对其他(有效)元素的点击冒泡并关闭上下文菜单,您将在中间处理程序中停止它的传播Event.stopPropagation
。document.onclick
也可以,但上下文菜单将保持可见,直到您释放鼠标按钮,而不是在您按下它时消失。在触摸设备中,您应该监听
document.touchstart
,因为某些设备(如 iPad)不会触发click
事件。Pressing Esc:听
document.onkeydown
并检查按下的键是否正在Esc检查KeyboardEvent.keyCode
,KeyboardEvent.which
和KeyboardEvent.key
。更改选项卡/窗口:听
window.onblur
。鼠标滚动:在 Chrome 中,听
document.onmousewheel
. 在这里查看有关如何在不同浏览器上检测鼠标滚轮的详细答案:鼠标滚轮、滚轮和 JavaScript 中的 DOMMouseScroll。发生这种情况时,无论页面是否有滚动,本机上下文菜单都会关闭,至少在 Windows 10 上的 Chrome 中是这样。
这是一个简单的示例,其中包含我提到的一些选项:
const contextMenu = document.getElementById('contextMenu');
const MARGIN = 10;
document.oncontextmenu = (e) => {
e.preventDefault();
const target = e.target;
if (contextMenu === target || contextMenu.contains(target)) {
// A right-click on the context menu itself (or anything inside it) will NOT reposition it:
return;
}
contextMenu.style.left = `${ Math.min(window.innerWidth - contextMenu.offsetWidth - MARGIN, Math.max(MARGIN, e.clientX)) }px`;
contextMenu.style.top = `${ Math.min(window.innerHeight - contextMenu.offsetHeight - MARGIN, Math.max(MARGIN, e.clientY)) }px`;
contextMenu.classList.remove('hidden');
};
contextMenu.onmousedown = (e) => {
// We don't want this click to close the context menu, so we stop its propagation:
e.stopPropagation();
};
// EVENTS THAT CLOSE THE CONTEXT MENU:
window.onblur = () => {
contextMenu.classList.add('hidden');
};
document.onmousedown = () => {
contextMenu.classList.add('hidden');
};
document.onmousewheel = () => {
contextMenu.classList.add('hidden');
};
document.onkeydown = (e) => {
if (e.key === 'Escape' || e.which === 27 || e.keyCode === 27) {
contextMenu.classList.add('hidden');
}
};
html,
body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
font-family: monospace;
}
#contextMenu {
box-sizing: border-box;
padding: 5px;
width: 200px;
min-height: 50px;
max-height: calc(100vh - 20px);
background: white;
position: fixed;
border-radius: 2px;
box-shadow: 0 0 32px rgba(0, 0, 0, .25);
transition: box-shadow ease-in 50ms;
}
#contextMenu:hover {
box-shadow: 0 0 48px rgba(0, 0, 0, .25);
}
#contextMenu:active {
box-shadow: 0 0 16px rgba(0, 0, 0, .25);
}
#contextMenuImage {
width: 100%;
border-radius: 2px;
display: block;
}
.hidden {
visibility: hidden;
}
<div id="contextMenu" class="hidden">
<img id="contextMenuImage" src="https://media1.giphy.com/media/3o7aTskHEUdgCQAXde/giphy.gif" />
</div>
RIGHT-CLICK TO SEE THE CONTEXT MENU
请注意,处理程序内部还有一个检查,oncontextmenu
以防止右键单击上下文菜单本身重新定位它。
推荐阅读
- java - 仅在具有 Windows 身份验证的两种情况之一中失败时如何解决“登录失败”错误(JDBC Java)
- python - 如何从羽毛字节对象读入数据帧
- sql - 需要帮助来理解下面的 oracle 代码
- python - Scipy 正弦拟合有错误的偏移量
- javascript - 从容器调用组件并根据父容器提供的输入参数呈现表单
- go - 安装 go 模块失败并显示“无效:模块包含 go.mod 文件,因此主要版本必须兼容”
- azure - 如何将 Azure 服务总线与事件中心集成?
- sql - SQL 中 AVG 函数后的重复行
- python - Tkinter 中的 ASCII 艺术与控制台中的不同
- python - Pandas Group-By 和 Sum 没有创建新的数据框