【问题标题】:My hover popup is flickering and moving when it shouldn't我的悬停弹出窗口在不应该的时候闪烁并移动
【发布时间】:2017-10-06 09:16:52
【问题描述】:

尝试创建一个在将鼠标悬停在元素上时将显示的弹出窗口。但是,当我在元素内移动鼠标时,它会闪烁并四处移动。如果鼠标移到弹出窗口上,它也应该保持打开状态。 尝试在没有像 jQuery 这样的库作弊的情况下做到这一点。如果你使用它们,你就不会学习。

如果您将鼠标悬停在以下标签之一上,这正是我想要创建的。

认为错误出在这段代码中:

function showPopup(e) {
    var popup = document.getElementById('popup');
    if (popup.style.display == 'none') {
        popup.style.display = 'block';

var bodyRect = document.body.getBoundingClientRect(),
    elemRect = e.target.getBoundingClientRect(),
    offsetX   = elemRect.left - bodyRect.left,
    offsetY   = elemRect.bottom - bodyRect.top;
        popup.style.left = offsetX + 'px';
        popup.style.top = offsetY + 'px';
        //console.log(e);
    }
}

function hidePopup(/*e*/) {
    setTimeout(function() {
        var popup = document.getElementById('popup');
        if (popup.style.display == 'block' && !window.inside_popup) {
            popup.style.display = 'none';
            window.inside_popup = false;
            console.log('hide');
        } else {
            setTimeout(hidePopup, 50); // try a little later
        }
    }, 50); // Give the events ability to catch up and tell us the mouse is inside the popup
}

var targ = document.querySelector('ul li')
    targ.addEventListener('mouseover', showPopup);
    targ.addEventListener('mouseout', hidePopup);

带有真实测试元素的完整 javascript 代码: https://jsfiddle.net/g8wvae8o/

【问题讨论】:

  • 你需要使用mouseenter和mouseleave

标签: javascript html css


【解决方案1】:

正如@epascarello 所说,mouseleavemouseenter 是您正在寻找的。这里也不需要setTimeout。此外,您要定位页面上的每个 li(这是故意的吗?)我建议定位特定类别的元素以减少闪烁。

这很接近,但您需要调整定位。

function createPopup() {
  var container = document.createElement('div');
  container.id = 'popup';
  container.style.width = '500px';
  container.style.height = '700px';
  container.style.display = 'none';
  container.style.position = 'absolute';
  container.style.borderRadius = '2px';
    container.style.border = '1px solid #242729';
    container.style.backgroundColor = '#535a60';
    container.style.color = '#e4e6e8';
    container.style.zIndex = '9999999';
  container.addEventListener('xmouseenter', function() {
    window.inside_popup = true;
    //console.log('window.inside_popup = true;');
  });
  container.addEventListener('xmouseleave', function() {
    window.inside_popup = false;
    //console.log('window.inside_popup = false;');
  });
  container.appendChild(document.createTextNode('This is a test'));
  (document.body || document.documentElement).appendChild(container);
}
window.inside_popup = false;
createPopup();


function showPopup(e) {
  var popup = document.getElementById('popup');
  if (popup.style.display == 'none') {
    popup.style.display = 'block';
  }
}

function hidePopup(/*e*/) {
  console.log('hiding')
  popup.style.display = 'none';
  window.inside_popup = false;
}

var bodyRect = document.body.getBoundingClientRect()
function updatePopup(e) {
  var elemRect = e.target.getBoundingClientRect(),
      offsetY   = elemRect.bottom - bodyRect.top,
      offsetX   = elemRect.left - bodyRect.left;
    popup.style.left = (e.clientX + offsetX) + 'px';
    popup.style.top = offsetY + 'px';
}

var targ = document.querySelector('ul li')
  targ.addEventListener('mouseenter', showPopup);
  targ.addEventListener('mouseleave', hidePopup);
  targ.addEventListener('mousemove', updatePopup)

Fiddle

【讨论】:

  • 每个 li 都包含一个指向所示产品的唯一链接,其中包含更多详细信息。悬停弹出窗口旨在提取它并将其显示在悬停弹出窗口中。如果你好奇这里是完整的链接systembolaget.se/dryck/ol/1664-blanc-151403
  • 为混乱的代码道歉,认为混乱是可读的。至于弹出窗口,它应该像标签弹出窗口tag popup一样在元素下方保持静止,并且提取详细信息的代码已经完成。它使用 XMLHttpRequest 和 document.implementation.createHTMLDocument,稍后编辑该页面的一部分将通过 .innerHTML 插入到悬停弹出窗口中
【解决方案2】:

这里是纯 CSS 解决方案(我只使用 JS 来创建弹出元素)

window.addEventListener("load", function () {
	var els = document.querySelectorAll("li");
    els.forEach(el => {
    	var popup = document.createElement("div");
        popup.innerHTML = el.getAttribute("popup");
        popup.className = "popup";
        el.appendChild(popup);
    });
});
*[popup]:hover > .popup {
    border: 1px solid #fff;
    padding: 0.5em;
    width: 400px;
    height: auto
}

.popup {
    overflow: hidden;
    box-sizing: border-box;
    background-color: black;
    color: #ccc;
    border-radius: 3px;
    position: absolute;
    height: 0px;
}

li {
    margin: 2em 0
}
<ul>
    <li popup="Some more info about this product">Move the mouse here</li>
    <li popup="Some more info about the 2nd product">Some other product</li>
</ul>

关键是弹出窗口是悬停元素的子元素,因此将鼠标移到弹出窗口上仍然算作悬停元素。

【讨论】:

  • 看起来不错,可以满足我的需求。但是在页面上不能正常工作(我正在尝试修改)。有什么东西在干扰。有些东西使弹出窗口出现但在元素的中间。在这种情况下,扩展网站以使其更好是很困难的。
  • 这是关于定位的;我将弹出窗口设置为absolute,它位于&lt;li&gt; 的正下方。只需将left:top: 属性添加到.popup 规则并尝试不同的px 值。
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 2020-04-30
  • 2016-09-23
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多