【问题标题】:Using setTimeout on hover interactions with a tooltip在带有工具提示的悬停交互上使用 setTimeout
【发布时间】:2021-10-11 14:36:07
【问题描述】:

我有一个由六边形组成的 SVG 地图,这些六边形被分成几组。当用户将鼠标悬停在一个组上时,我希望出现一个工具提示。问题是,我希望这个工具提示有 3 秒的延迟。因此,如果用户决定在该延迟期间悬停,我想清除该延迟以阻止工具提示出现,因为他们不再悬停在它上面。工具提示消失的时间也会有延迟,以防您在快速离开前一个元素后将鼠标悬停在另一个元素上。

我为此使用了 setTimeout。我在这里所做的工作有 50% 的时间有效,但我发现如果我将鼠标悬停在上面并让工具提示显示,然后在悬停之前快速将鼠标悬停在一堆其他不同的元素上,工具提示会消失但很快再次出现。

这是我的代码,如果需要,我很乐意进一步解释。干杯!

// Setting the tooltip to appear below the tooltip wrapper
gsap.set(tip, {
    yPercent: 100
});

// Tooltip Hovering Functionality with Timeouts
let hoverOutTimeout; // Timeout for hovering out

// GO through grouped elements with an event listener on mouse move, and use timeouts to delay hover
for (i = 0; i < lgas.length; i++) {
    lgas[i].onmouseover = function () {
        if (hoverOutTimeout) { // Check to see if the delay for the mouseleave function is running
            clearTimeout(hoverOutTimeout);
            //console.log("Hover back in");
        } else {
            //console.log("Hovering in");
        }

        // Set 3s delay to display tooltip
        hoverTimeout = setTimeout(function () {
            //console.log("Hovered in");

            gsap.to(tip, {
                yPercent: 0,
                ease: 'bounce.out'
            });
        }, 3000);
    }

    lgas[i].onmouseleave = function () {
        if (hoverTimeout) { // If delay to show tooltip is running, clear it
            clearTimeout(hoverTimeout);
            //console.log("Hovering back out")

            hoverOutTimeout = setTimeout(() => { // Start new delay to hide tooltip
                //console.log("Hovered out");

                gsap.to(tip, {
                    yPercent: 100,
                    ease: 'back.in'
                });
            }, 2000);

        }
        clearTimeout(hoverTimeout);
    }
}

【问题讨论】:

    标签: javascript html css gsap


    【解决方案1】:

    我能够通过将事件绑定到关联的 ID 来实现这一点。这个想法是 setTimeout 将检查它的 ID 是否是当前生成的 ID。 ID 是在事件绑定时生成的。

    在 mouseenter 上,事件与当前生成的 ID 相关联。在 mouseleave 上,事件被取消绑定,然后使用新生成的 ID 重新绑定。这种方法可以防止悬停堆叠。

    我希望这有点道理。我开发了一个 sn-p 来进行实验。

    let bindCurID;
    
    let hoverBinder = function(){
      bindCurID = new Date() * Math.random();
      
      $('div').off('mouseenter').on('mouseenter', function(){
        let sMsg = $(this).find('h2').text();
        let bindID = bindCurID;
        
        setTimeout(function(){
          if(bindID != bindCurID)
            return
          $('body').append('<span class="hov">' + sMsg + '</span>');
        }, 2000)
        
      });
      
      $('div').off('mouseleave').on('mouseleave', function(){
        $('.hov').remove();
        hoverBinder()
      });
    }
    
    hoverBinder()
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="div1" style='background-color:lightblue'>
    <h2>Hello</h2>
    </div><br /><br />
    <div id="div2" style='background-color:lightblue'>
    <h2>World</h2>
    </div>

    我敢肯定还有其他人可以通过某种魔法技巧在一条线上完成所有这些工作,但这将完成工作。

    【讨论】:

      【解决方案2】:

      您的某些代码缺少您的帖子,因此我冒昧地提供了示例 DOM 结构和通用函数来显示/隐藏工具提示。在下面的代码中,每个元素的背景颜色将根据工具提示是否可见而改变。关键概念是您需要为每个元素存储一些状态(其timerId)。

      const SHOW_DELAY = 1500;
      const HIDE_DELAY = 1200;
      
      function showTooltip(element) {
        element.classList.add('hovered');
      }
      
      function hideTooltip(element) {
        element.classList.remove('hovered');
      }
      
      function setTooltips(elements) {
        function getMouseEventHandler(elementHandler, delay) {
          return ({target: element}) => {
            let timerId = timerIdMap.get(element) ?? 0;
            clearTimeout(timerId);
            timerId = setTimeout(() => elementHandler(element), delay);
            timerIdMap.set(element, timerId);
          };
        }
      
        const handleMouseEnter = getMouseEventHandler(showTooltip, SHOW_DELAY);
        const handleMouseLeave = getMouseEventHandler(hideTooltip, HIDE_DELAY);
      
        const timerIdMap = new WeakMap();
      
        for (const element of elements) {
          timerIdMap.set(element, 0);
          element.addEventListener('mouseenter', handleMouseEnter);
          element.addEventListener('mouseleave', handleMouseLeave);
        }
      }
      
      const elements = [...document.querySelectorAll('div.item')];
      setTooltips(elements);
      .container {
        display: flex;
        flex-wrap: wrap;
        width: 14rem;
      }
      
      .item {
        border: 1px solid;
        height: 3rem;
        width: 3rem;
      }
      
      .hovered {
        background-color: orangered;
      }
      <div class="container">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-21
        • 1970-01-01
        • 1970-01-01
        • 2015-12-07
        • 2012-06-18
        • 1970-01-01
        • 2014-03-29
        • 2017-01-30
        相关资源
        最近更新 更多