Mouseenter 和 mouseleave - 在触发功能前稍等片刻?

Mouseenter and mouseleave - wait a moment before triggering function?

我有一个元素 CSS 我想在用户将鼠标移入或移出时对其进行更改。触发它的一些函数,足够简单:

function expandDiv(){
  div1.classList.add('expanded')
}

function shrinkDiv(){
  div1.classList.remove('expanded')
}

但是,我希望用户在函数实际触发之前将鼠标悬停在(或远离)该元素上一小会儿(比如 200 毫秒)。这是为了可用性,因为快速通过元素不应触发该功能。这个问题已经讨论 here,我喜欢这个解决方案:

var delay = function (elem, callback) {
var timeout = null;
    elem.onmouseover = function() {
        // Set timeout to be a timer which will invoke callback after 1s
        timeout = setTimeout(callback, 1000);
    };

    elem.onmouseout = function() {
        // Clear any timers set to timeout
        clearTimeout(timeout);
    }
};

但当回调函数是我的 expandDiv()shrinkDiv() 函数时,此解决方案仅适用于一个方向。我尝试简单地用 delay() 结构编写 2 个函数并反转 onmouseoutonmouseenter 事件:

// Delay functions
var delayIn = function (elem, callback) {
    var timeout = null;
    elem.onmouseover = function() {
        // Set timeout to be a timer which will invoke callback after 1s
        timeout = setTimeout(callback, 1000);
    };

    elem.onmouseout = function() {
        // Clear any timers set to timeout
        clearTimeout(timeout);
    }
};

var delayOut = function (elem, callback) {
    var timeout = null;
    elem.onmouseout = function() {
        // Set timeout to be a timer which will invoke callback after 1s
        timeout = setTimeout(callback, 200);
    };

    elem.onmouseover = function() {
        // Clear any timers set to timeout
        clearTimeout(timeout);
    }
};

delayIn(div1, expandDiv);
delayOut(div1, shrinkDiv);

但这不起作用。当 delayIn 和 delayOut 都被调用时,delayIn 函数什么都不做。请参阅此代码笔:

https://codepen.io/slutske22/pen/eYYzQqE?editors=0010

我不确定出了什么问题。 div 应该在将鼠标悬停在其上一秒钟后展开,除非您在第二个结束之前将鼠标移出。但它什么都不做。我添加了一个 "Expand the Div" 按钮来强制它,你可以看到,如果你然后将鼠标悬停在 div 和 mouseout 上,它确实会从 shrinkDiv 函数中收缩,但没有延迟应该来自 delayOut 函数。

我也在尝试 link 将此行为添加到按钮中。有一个 "Shrink the div" 按钮。期望的行为是您单击按钮,并且 div 将在定义的 setTimout 延迟后收缩,除非您 在超时结束前鼠标输入 div。这也没有发生。

我觉得这是一个相对简单的任务,但它让我望而却步。我想学习如何在没有 jQuery 的情况下进行操作。我也意识到这可能应该是 this thread 中的一个表扬,但我是新手,还不能发表评论。对不起,如果这是错误的形式。

您在 delayIn 中分配的 onmouse* 处理程序在 delayOut 中被覆盖 - 这就是为什么只有一个 "animations" 做它应该做的事

var div1 = document.querySelector('#div1')
var button = document.querySelector('#button')


function expandDiv(){
  div1.classList.add('expanded')
}

function shrinkDiv(){
  div1.classList.remove('expanded')
}


var delayInOut = function(elem, incb, outcb) {
    var timeout = null;
    var clearto = function() {
      clearTimeout(timeout);
      timeout = null;
    };
    elem.onmouseover = function() {
      clearto();
      timeout = setTimeout(incb, 1000);
    }
    elem.onmouseout = function() {
      clearto();
      timeout = setTimeout(outcb, 200);
    }
}
delayInOut(div1, expandDiv, shrinkDiv);


expandButton.onclick = expandDiv

shrinkButton.addEventListener("click", function(){
  var timeout = setTimeout(shrinkDiv, 1000);
}, false)
body{
  position: relative;
  padding: 0px;
  margin: 0px;
}
#div1{
  position: absolute;
  top: 20px;
  left: 20px;
  right: 20px;
  height: 50px;
  background-color: darkblue;
  transition: height 1s;
}
#div1.expanded{
  height: 70px;
}

#expandButton{
  position: absolute;
  left: 20px;
  top: 100px;
}
#shrinkButton{
  position: absolute;
  left: 20px;
  top: 125px;
}
<body>
  <div id="div1"></div>
  <button id="expandButton">Expand Div</button>
  <button id="shrinkButton">Shrink Div After Delay</button>
</body>

As a point of interest, you can achieve this without javascript, including having different delays for expanding and contracting:

body{
  position: relative;
  padding: 0px;
  margin: 0px;
}
#div1{
  position: absolute;
  top: 20px;
  left: 20px;
  right: 20px;
  height: 50px;
  background-color: darkblue;
  transition: height 1s ease-in-out 200ms;
}
#div1:hover{
  transition-delay:1s;
  height: 70px;
}
<body>
  <div id="div1"></div>
</body>