Страницы

Поиск по вопросам

вторник, 24 декабря 2019 г.

Всплывающая подсказка на объекте с задержкой

#javascript #jquery


Есть несколько рядом лежащих объектов, наводя на каждый из них возникает подсказка
с анимацией (список 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;
}

123
Добавлено. Если у всплывающей подсказки убрать дополнения по расположению т.е. добавленные 50 и 30 пикселей то ошибка с появлением и исчезновением подсказки похожа на ту что у меня.


Ответы

Ответ 1



$(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; }
123


Ответ 2



подобные интерфейсные "фичи", хоть и кажутся простыми на первый взгляд, но на самом деле достаточно сложны в реализации. Да просто показать/скрыть, но достигнуть стабильной и "красивой" работы в разных браузерах и стеках о-о-очень сложно. Используйте опыт сообщества, к примеру: https://popper.js.org/ https://atomiks.github.io/tippyjs/ Одним debounce здесь не обойтись, нужно предусмотреть все возможные варианты поведения, плюс варианты при изменении размеров окна. Однозначно ответить на вопрос нет возможности. Это все равно не будет правильным ответом.

Комментариев нет:

Отправить комментарий