知道鼠标是否在元素上的替代方法 (Javascript)

Alternative way to know if mouse is over an element (Javascript)

我有一个脚本,当我的鼠标悬停在它上面时,它会显示一个“悬停元素”(如缩放)。我知道这有点乱,但这里有一个例子:

function showOverflow2(e) {
  let cell = e.currentTarget;
  let clone = cell.cloneNode(true);

  if (cell.children[0].scrollWidth <= cell.children[0].clientWidth) {
    return false;
  };

  clone.innerHTML = clone.children[0].innerHTML;

  clone.style.position = 'absolute';

  clone.style.backgroundColor = 'white';
  clone.style.borderWidth = '2px';

  clone.style.lineHeight = cell.scrollHeight + 'px';

  clone.style.whiteSpace = 'nowrap';


  x0 = (
    cell.offsetLeft +
    parseFloat(
      getComputedStyle(
        cell.parentElement.parentElement.parentElement.parentElement
      )["padding-left"].slice(0, -2)
    ) + 2
  );

  y0 = (
    cell.offsetTop +
    parseFloat(
      getComputedStyle(
        cell.parentElement.parentElement.parentElement.parentElement
      )["padding-top"].slice(0, -2)
    ) + 2
  );

  xmid = x0 + (cell.clientWidth / 2);
  ymid = y0 + (cell.clientHeight / 2);

  let body = document.getElementsByTagName('body')[0];
  body.appendChild(clone);

  clone.style.height = cell.scrollHeight + 'px';
  clone.style.width = clone.scrollWidth + 'px';

  xf = xmid - (clone.clientWidth / 2);
  yf = ymid - (clone.clientHeight / 2);

  clone.style.top = yf + 'px';
  clone.style.left = xf + 'px';

  
  // FOCUS ON THIS PART
  

  clone.addEventListener("mouseout", function() {
    clone.remove();
  });
  
  // END OF FOCUS
  
};



let all_cells = document.getElementsByTagName('td');
for (let i = 0; i < all_cells.length; i++) {
  let current_cell = all_cells[i];

  if (current_cell.className !== 'buttons') {
    current_cell.addEventListener("mouseover", showOverflow2);
  }
}
body {
  margin: 0;
}

#container {
  background-color: gainsboro;
  border: 2px solid black;
  border-radius: 2px;
  padding: 1.2%;
  max-width: 50%;
}

table {
  border-collapse: separate;
  border-spacing: 0 0.5rem;
  table-layout: fixed;
  width: 100%;
}

tr {
  background-color: white;
}

td {
  width: calc(100%/3);
  border: solid gray;
  border-width: 2px 1px 2px 0;
  padding: 0.7% 1%;
  text-align: center;
  white-space: nowrap;
}

span {
  display: block;
  overflow: hidden;
}

td:first-child {
  border-left-width: 2px;
  border-radius: 3px 0 0 3px;
}

td:last-child {
  border-right-width: 2px;
  border-radius: 0 3px 3px 0;
}
<div id="container">
  <table id="table">
    <tr>
      <td class="cell1"><span>AAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
  </table>
</div>

要删除“缩放”和 return 正常的东西,我只是使用:

    clone.addEventListener("mouseout", function() {
    clone.remove();

如果您将鼠标平滑地移到元素上,这会很好地工作,但是如果移动得更大 table 和移动得更快,您可以亲眼看到某些元素 return 不正常:

function showOverflow2(e) {
  let cell = e.currentTarget;
  let clone = cell.cloneNode(true);

  if (cell.children[0].scrollWidth <= cell.children[0].clientWidth) {
    return false;
  };

  clone.innerHTML = clone.children[0].innerHTML;

  clone.style.position = 'absolute';

  clone.style.backgroundColor = 'white';
  clone.style.borderWidth = '2px';

  clone.style.lineHeight = cell.scrollHeight + 'px';

  clone.style.whiteSpace = 'nowrap';


  x0 = (
    cell.offsetLeft +
    parseFloat(
      getComputedStyle(
        cell.parentElement.parentElement.parentElement.parentElement
      )["padding-left"].slice(0, -2)
    ) + 2
  );

  y0 = (
    cell.offsetTop +
    parseFloat(
      getComputedStyle(
        cell.parentElement.parentElement.parentElement.parentElement
      )["padding-top"].slice(0, -2)
    ) + 2
  );

  xmid = x0 + (cell.clientWidth / 2);
  ymid = y0 + (cell.clientHeight / 2);

  let body = document.getElementsByTagName('body')[0];
  body.appendChild(clone);

  clone.style.height = cell.scrollHeight + 'px';
  clone.style.width = clone.scrollWidth + 'px';

  xf = xmid - (clone.clientWidth / 2);
  yf = ymid - (clone.clientHeight / 2);

  clone.style.top = yf + 'px';
  clone.style.left = xf + 'px';

  
  // FOCUS ON THIS PART
  

  clone.addEventListener("mouseout", function() {
    clone.remove();
  });
  
  // END OF FOCUS
  
};



let all_cells = document.getElementsByTagName('td');
for (let i = 0; i < all_cells.length; i++) {
  let current_cell = all_cells[i];

  if (current_cell.className !== 'buttons') {
    current_cell.addEventListener("mouseover", showOverflow2);
  }
}
body {
  margin: 0;
}

#container {
  background-color: gainsboro;
  border: 2px solid black;
  border-radius: 2px;
  padding: 1.2%;
  max-width: 50%;
}

table {
  border-collapse: separate;
  border-spacing: 0 0.5rem;
  table-layout: fixed;
  width: 100%;
}

tr {
  background-color: white;
}

td {
  width: calc(100%/3);
  border: solid gray;
  border-width: 2px 1px 2px 0;
  padding: 0.7% 1%;
  text-align: center;
  white-space: nowrap;
}

span {
  display: block;
  overflow: hidden;
}

td:first-child {
  border-left-width: 2px;
  border-radius: 3px 0 0 3px;
}

td:last-child {
  border-right-width: 2px;
  border-radius: 0 3px 3px 0;
}
<div id="container">
  <table id="table">
    <tr>
      <td class="cell1"><span>AAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAAaAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAASAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
    <tr>
      <td class="cell1"><span>AAAAAAAAAABBBCC</span></td>
      <td class="cell2"><span>AAAAAAAAAABBBB</span></td>
      <td class="cell3"><span>AAAAAAAAAAAAABBBBB</span></td>
      </td>
    </tr>
  </table>
</div>

如果我不相信 mouseout 事件,我可以做些什么来解决这个问题?

我考虑过在鼠标移动时使用 eventListener 以使用绝对坐标测试鼠标是否在元素内部,但可能有更简单的解决方案。

您可以使用 CSS 重复内容(放大)并在悬停时显示和隐藏它来做类似的事情。下面的简单示例。

table {
  padding: 30px;
}

td {
  position: relative;
  padding: 4px;
  border: 1px solid blue;
}

.grow {
  display: none;
  background-color: #fff;
  border: 1px solid #000;
  padding: 3px;
  z-index: 10;
}

td:hover .grow {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  transform: scale(1.5);
}
<html>

<head></head>

<body>
  <table>
    <tr>
      <td>asdf<span class="grow">ASDF</span></td>
      <td>fasd<span class="grow">FASD</span></td>
  </table>
</body>

</html>

我正在回答我自己的问题,因为我需要结合一些想法才能让它运作良好。

首先我需要指出的是,出于某种原因,我描述的问题仅在打开“开发人员”选项卡 (f12) 时在浏览器中发生,否则一切正常。

但我仍然想确定没有细胞会那样冻结,所以我像 Ed Lucas 一样使用 css。尽管如此,我仍需要 Javascript 才能正确居中。

经过几天的尝试,我终于找到了一种使用 css 将其居中的方法,该方法使用绝对定位并且子元素更大。

我没有删除 Javascript 方法,因为它使我可以灵活地使用命令来触发和恢复此事件。

最后,我的代码是这样的:

function showOverflow(e) {

  const div = e;
  const cell = div.parentElement;
  const span = div.children[0];

  if (span.scrollWidth <= span.clientWidth) {
    return false;
  }

  const clone = div.cloneNode(true);
  clone.classList.add('hovercell');

  cell.appendChild(clone);

  let cell_style = getComputedStyle(cell);

  function cloneRemove(host) {
    clone.remove();
    clearInterval(host.id);
  }

  function isInside(host) {
    if (cell_style['z-index'] === '0') {
      cloneRemove(host);
    }
  }

  let host = {};
  host.id = setInterval(isInside.bind(null, host), 100);

  clone.addEventListener("mouseleave", function() {
    cloneRemove(host);
  });

}
td {
  border: 2px solid gray;
  padding: 0.7% 1%;
  text-align: center;
  white-space: nowrap;
  z-index: 0;
  position: relative;
}

td:hover {
  z-index: 2;
}

span {
  display: block;
  overflow: hidden;
}

.hovercell {
  background-color: white;
  border: 2px solid gray;
  
  padding: 6px 8px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(1.2);
}
<table>
  <tbody>
    <tr>
      <td>
        <div onclick="showOverflow(this)">
          <span>A big cell--- 1</span>
        </div>
      </td>
      <td>
        <div onclick="showOverflow(this)">
          <span>A big cell--- 2</span>
        </div>
      </td>
    </tr>
  </tbody>
</table>

希望对大家有所帮助。