Есть несколько рядом лежащих объектов, наводя на каждый из них возникает подсказка с анимацией (список ul, в котором li плавно появляются один за другим). Так как элементов много и пользователь может резко водить по ним, решил сделать задержку в виде debounce(f, 150ms). Но теперь если провести случайно мышкой по объекту и не взаимодействовать впринципе ни с чем то появляется подсказка последнего задетого объекта (оно и логично), так как debounce срабатывает позже чем сработал .stop().fadeOut(). А так же иногда появляется баг, что если в рукой дернуть например с одного объекта на другой (не стал воссоздавать здесь, может так кто то разберется, если нет то приведу пример постараюсь), то подсказка возникает под курсором, но так как она перекрывает объект, который показывает то она тут же исчезает и снова мышка на обекте, подсказка появляется и все зацикливается.
function debounce(f, ms) {
let timer = null;
return function (...args) {
const onComplete = () => {
f.apply(this, args);
timer = null;
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(onComplete, ms);
};
}
function renderHint() {
$('#hint').stop().append('123').fadeIn('100');
}
let renderHintDebounce = debounce(renderHint, 150);
$('.block').on('mouseenter', function(e) {
$('#hint').empty();
$(this).mousemove(function(pos) {
$("#hint")
.css('left', (pos.pageX + 50)+'px')
.css('top', (pos.pageY - 30)+'px');
});
renderHintDebounce();
});
$('.block').on('mouseleave', function(e) {
$('#hint').stop().fadeOut(100).queue(function() {
$(this).empty().dequeue();
})
});
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.block {
width: 100px;
height: 100px;
background: red;
}
#hint {
position: absolute;
display: none;
background: #eee;
}
Добавлено. Если у всплывающей подсказки убрать дополнения по расположению т.е. добавленные 50 и 30 пикселей то ошибка с появлением и исчезновением подсказки похожа на ту что у меня.
Ответ
$(function(){ let hint=$('#hint'), hintTimer, fadeTime=400 $('.block').on('mouseenter', function(e) { let el=$(this) el.mousemove(function(pos) { hint .css('left', (pos.pageX + 50)+'px') .css('top', (pos.pageY - 30)+'px'); }); hintTimer=setTimeout(()=>hint.html(el.attr('hint')).fadeIn(fadeTime),fadeTime) }); $('.block').on('mouseleave', function(e) { if(hintTimer) clearTimeout(hintTimer) hint.off('mousemove').fadeOut(fadeTime) }); }) .container { display: flex; justify-content: center; align-items: center; height: 100vh; width: 100vw; } .block { width: 100px; height: 100px; background: red; border:1px solid white; } #hint { position: absolute; display: none; background: #eee; }