如何在所有图层上获取鼠标事件?

时间:2018-11-08 19:21:51

标签: javascript jquery

我有一个带有一些重叠元素的网格(请参见代码段中的模型)。我需要将鼠标事件定向到不同的层。

单击鼠标左键应转到网格单元格(我必须知道单击了哪个单元格)。右键单击应覆盖。我该怎么办?

目前我已经设法获得:

  • [snippet]右键单击可以正常工作,左键单击重定向到重叠式广告的父级(可能与直接位于其下的内容不同)
  • [没有z-index的代码段]左键单击正常,只有在单击覆盖层与其父单元格重叠的位置时,右键单击才起作用

var eventDescription = $('span');

$('table').on('click', 'td', function() {
  var cell = $(this);

  var column = 1 + cell.index();
  var row = 1 + cell.closest('tr').index();
  
  eventDescription.text('Left click on cell ' + row + ', ' + column + '.');
});

$('table').on('contextmenu', 'div', function() {
  eventDescription.text('Right click on ' + this.getAttribute('id') + '.');
  return false;
});
table {
  border-collapse: collapse;
}

td {
  position: relative;
  border: 1px black solid;
  height: 20px;
  width: 20px;
}

div {
  position: absolute;
  top: 2px;
  left: 2px;

  background-color: #e52e4e;
  width: 62px;
  height: 16px;
  z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
  <tr><td><td><td><td><td>
  <tr><td><td><div id="bar1"></div></td><td><td><td>
  <tr><td><td><td><td><td>
  <tr><td><td><td><td><td>
  <tr><td><div id="bar2"></div><td><td><td><td>
</table>

<span></span>

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,那么一种解决方案是在鼠标的“左键单击”事件周期内,防止带有div(即覆盖)元素的“指针事件”。

您可以通过mousedown事件来拦截点击周期的开始-此时,您可以使用<div/>来切换pointer-events:none(重叠)元素的类,以防止后续的鼠标/ pointer-events触发您的div。

这样做,您允许左键单击事件有效地绕过<div/>元素,这意味着相应的mouseup将响应<td/>“,就好像div不是在那里”。

然后,您可以使用mouseup事件来做两件事:

  1. 执行td / cell检测逻辑(以前在常规click事件中发生)
  2. 通过再次切换指针事件类来恢复div元素的默认指针事件行为

这是一个可行的示例:

var eventDescription = $('span');

$('table').on('mousedown', 'td', function(event) {

  // When td is left clicked, toggle the 'stop-events' class
  // on all div/overlay elements. This prevents the divs from
  // firing the contextmenu/rightclick event that you want to
  // distinguish for those
  if(event.button === 0) {
    for(const node of document.body.querySelectorAll('div')) {
      node.classList.toggle('stop-events')
    }
  }
})

$('table').on('mouseup', 'td', function(event) {

  // If left mouse button released on td, perform the regular
  // cell detection logic, but also restore the default point-events
  // behaviour so that divs still respond to context click
  if(event.button === 0) {
    
    var cell = $(this);

    var column = 1 + cell.index();
    var row = 1 + cell.closest('tr').index();

    eventDescription.text('Left click on cell ' + row + ', ' + column + '.');
  
    // Restore default pointer events to allow contextmenu events
    // on divs
    for(const node of document.body.querySelectorAll('div')) {
      node.classList.toggle('stop-events')
    }
  }
})


$('table').on('contextmenu', 'div', function() {

  eventDescription.text('Right click on ' + this.getAttribute('id') + '.');
  return false;
});
table {
  border-collapse: collapse;
}

td {
  position: relative;
  border: 1px black solid;
  height: 20px;
  width: 20px;
}

div {
  position: absolute;
  top: 2px;
  left: 2px;
  background-color: #e52e4e;
  width: 62px;
  height: 16px;
  z-index: 2;
}

/* Added this class */
.stop-events {
  pointer-events:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
  <tr><td><td><td><td><td>
  <tr><td><td><div id="bar1"></div></td><td><td><td>
  <tr><td><td><td><td><td>
  <tr><td><td><td><td><td>
  <tr><td><div id="bar2"></div><td><td><td><td>
</table>

<span></span>