Mouseenter и mouseleave - подождите немного, прежде чем активировать функцию? - PullRequest
1 голос
/ 17 октября 2019

У меня есть элемент, CSS которого я хочу изменить, когда пользователь включается или выключается. Некоторые функции для запуска этого достаточно просты:

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

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

Тем не менее, я хочу, чтобы пользователь на короткое время (скажем, 200 мсек) находился над (или отстранялся) от этого элемента, прежде чем функция фактически сработает. Это для удобства использования, так как быстрый переход к элементу не должен вызывать функцию. Эта проблема обсуждалась здесь , и мне понравилось это решение:

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() функцией. Я попытался просто написать 2 функции со структурой delay() и обратить вспять события onmouseout и onmouseenter:

// 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 должен расшириться после секунды наведения на него, если вы не наведите курсор мыши до того, как вторая закончится. Но это ничего не делает. Я добавил кнопку «Развернуть Div», чтобы вызвать ее, и вы можете видеть, что если затем навести курсор мыши на div и mouseout, он действительно сжимается, как и должно быть с помощью функции shrinkDiv, но нет задержки, как это должно быть сФункция delayOut.

Я также пытаюсь связать это поведение с кнопкой. Есть кнопка «Уменьшить div». Желаемое поведение заключается в том, что вы нажимаете кнопку, и div сжимается после заданной задержки setTimout, , если вы не введете мышь в div до истечения времени ожидания. Этого тоже не происходит.

Я чувствую, что это относительно простая задача, но она ускользает от меня. Я хотел бы узнать, как это сделать без jQuery. Кроме того, я понимаю, что это, вероятно, следует отметить в этой теме , но я новичок и пока не могу комментировать. Извините, если это дурной тон.

1 Ответ

1 голос
/ 17 октября 2019

обработчики onmouse *, которые вы назначаете в delayIn, перезаписываются в delayOut - поэтому только одна из «анимаций» делает то, что должна

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>

В качестве точки интереса вы можете достичь этого без JavaScript, включая различные задержки для расширения и сжатия:

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>
...