首页 > 解决方案 > 如何使用 VANILLA JS 按住右键单击来执行 eventListener

问题描述

我想在光标按住右键的任何地方显示 div。

就我而言,我有这个代码

<div class="d-none" id="item"></div>
#item{
  position: absolute;
  top: 0;
  left: 0;
  width: 100px;
  height: 100px;
  background: royalblue;
  /* transform: translate(calc(287px - 50%), calc(77px - 50%)); */
}
.d-none{
  display: none;
}
var myMouseX, myMouseY;

function getXYPosition(e) {
    myMouseX = (e || event).clientX;
    myMouseY = (e || event).clientY;
    
    getPosition(myMouseX, myMouseY);
    
    
    function getPosition(x, y) {
        console.log('X = ' + x + '; Y = ' + y);
      let div = document.querySelector("#item");
      if (div.classList.contains('d-none')) {
        div.classList.remove('d-none');
      } else {
        div.classList.add('d-none');
      }
      divX = x + "px";
      divY = y + "px";
      div.style.transform = `translate(calc(`+divX+` - 50%) , calc(`+divY+` - 50%))`;
    }
}

window.addEventListener('click', function () {
  getXYPosition()
})

或者你可以看看我的小提琴

默认情况下,它在左键单击时使用window.addEventListener('click')

那么我如何从左键单击更改为按住右键单击几秒钟

标签: javascripthtmlcss

解决方案


MouseEvent API(及其mousedownmouseup事件)让我们检查event.button属性以了解用户正在激活哪个鼠标按钮。我们可以跟踪之间经过了多少时间,mousedownmouseup决定释放鼠标按钮时要做什么,例如运行自定义showOrHideDiv函数。

并且在右键单击后触发contextmenu事件(除非相关的上下文菜单已经可见,我猜。)如果需要,我们可以抑制默认的上下文菜单行为——尽管如果有的话,应该谨慎使用这种能力。

请注意,这里使用的技术是有问题的,因为它假定用户永远不会使用他们的键盘来查看上下文菜单,这最终会给用户带来可访问性混乱和其他令人不快的惊喜。right-click这就是为什么如果可能的话应该避免劫持默认行为(可能有利于类似的东西Shift + right-click),除非用户明确选择接受新行为。

// Defines constants and adds main (`mousedown`) listener
const
  div = document.querySelector("#item"),
  RIGHT = 2,
  DELAY = 150;
document.addEventListener('mousedown', forceDelay);

// Main listener sets subsequent listeners
function forceDelay(event){

  // Right mouse button must be down to proceed
  if(event.button != RIGHT){ return; }

  // Enables contextmenu and disables custom response
  document.removeEventListener('contextmenu', suppressContextMenu);
  document.removeEventListener('mouseup', showOrHideDiv);

  // After 150ms, disables contextmenu and enables custom response
  setTimeout(
    function(){
      document.addEventListener('contextmenu', suppressContextMenu);
      document.addEventListener('mouseup', showOrHideDiv);
    },
    DELAY
  );
}

// The `contextmenu` event listener
function suppressContextMenu(event){
  event.preventDefault();
}

// The `mouseup` event listener
function showOrHideDiv(event){
  if(event.button != RIGHT){ return; }
  const
    x = event.clientX,
    y = event.clientY;
  div.classList.toggle('d-none'); // classList API includes `toggle`
  div.style.transform = `translate(calc(${x}px - 50%), calc(${y}px - 50%))`;
}
#item{ position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: royalblue; }
.d-none{ display: none; }
<div id="item" class="d-none"></div>

编辑
注意:当使用 Chrome 在独立的 HTML 文件中进行测试时,该脚本可以正常工作,但是(至少在我笔记本电脑的触摸板中)在 Stack Overflow 代码段中运行时表现得很奇怪。如果您遇到类似问题,可以将其粘贴到 HTML 文件中的 <script> 元素中(在 <style> 元素中使用 CSS)以查看它是否正常工作。


推荐阅读