【问题标题】:How can I run a function when an element enters the viewport?当元素进入视口时如何运行函数?
【发布时间】:2021-11-19 18:00:13
【问题描述】:

我有一个计数器统计信息,它工作正常,但我如何编写一个条件,它应该只在父级在视口中时才启动?也许我的语法是错误的,或者我不明白如何连接我得到的东西。任何建议表示赞赏。

这是我现在得到的:

$(window).scroll(function() {
  if ($('.numbers-inner').isInViewport()) {
    //then what?;

  } else {
    //else what?;
  }
});
$('.magPub, .pplHired, .yrsExp').each(function() {
  $(this).prop('Counter', 0).animate({
    Counter: $(this).text()
  }, {
    duration: 1500,
    easing: 'swing',
    step: function(now) {
      $(this).text(Math.ceil(now));
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="numbers-inner stats">
  <ul>
    <li><span class="magPub">33708</span>+</li>
    <li>magazines published</li>
  </ul>

  <ul>
    <li><span class="pplHired">247</span></li>
    <li>people hired</li>
  </ul>

  <ul>
    <li><span class="yrsExp">17</span></li>

    <li>years of experience</li>
  </ul>

</div>

【问题讨论】:

    标签: jquery counter


    【解决方案1】:

    这将在您的父母变得可见时触发动画,并且只会动画一次。

    let hasBeenAnimated = false;
    
    $.fn.isInViewport = function () {
        let elementTop = $(this).offset().top;
        let elementBottom = elementTop + $(this).outerHeight();
    
        let viewportTop = $(window).scrollTop();
        let viewportBottom = viewportTop + window.innerHeight;
    
        return elementBottom > viewportTop && elementTop < viewportBottom;
      };
    
    function animate() {
        $('.magPub, .pplHired, .yrsExp').each(function() {
            $(this).prop('Counter', 0).animate({
                Counter: $(this).text()
            }, {
                duration: 1500,
                easing: 'swing',
                step: function(now) {
                    $(this).text(Math.ceil(now));
                }
            });
        });
    }
    
    $(window).scroll(function() {
        if ($('.numbers-inner').isInViewport() && !hasBeenAnimated) {
            hasBeenAnimated = true;
            animate();
        }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div style="height: 2000px">
      <h1>↓↓↓ SCROLL DOWN ↓↓↓</h1>
    </div>
    <div class="numbers-inner stats" style="background: red">
      <ul>
        <li><span class="magPub">33708</span>+</li>
        <li>magazines published</li>
      </ul>
    
      <ul>
        <li><span class="pplHired">247</span></li>
        <li>people hired</li>
      </ul>
    
      <ul>
        <li><span class="yrsExp">17</span></li>
    
        <li>years of experience</li>
      </ul>
    
    </div>

    请注意.isInViewport() 不是jQuery 函数,而是用户在this question 中实现的自定义函数。还要注意原始函数有一个错误,这是正确的实现:

    $.fn.isInViewport = function () {
      let elementTop = $(this).offset().top;
      let elementBottom = elementTop + $(this).outerHeight();
    
      let viewportTop = $(window).scrollTop();
      let viewportBottom = viewportTop + window.innerHeight;
    
      return elementBottom > viewportTop && elementTop < viewportBottom;
    };
    

    【讨论】:

      【解决方案2】:

      JavaScript 有一个 intersection observer API 可以做到这一点。您设置要观察的元素,其余的由它完成。在下面的示例中,我们将阈值设置为 50%(当 50% 的 div 显示时,将执行该函数开始计数):

      const target = document.querySelector('.numbers-inner.stats');
      
      function handleIntersection(entries) {
        entries.map((entry) => {
          if (entry.isIntersecting) {
            $('.magPub, .pplHired, .yrsExp').each(function() {
              $(this).prop('Counter', 0).animate({
                Counter: $(this).text()
              }, {
                duration: 1500,
                easing: 'swing',
                step: function(now) {
                  $(this).text(Math.ceil(now));
                }
              });
            });
          }
        });
      }
      
      let opts = {
        threshold: 0.5
      }
      
      const observer = new IntersectionObserver(handleIntersection, opts);
      observer.observe(target);
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div>&nbsp;</div>
      <div class="numbers-inner stats">
        <ul>
          <li><span class="magPub">33708</span>+</li>
          <li>magazines published</li>
        </ul>
      
        <ul>
          <li><span class="pplHired">247</span></li>
          <li>people hired</li>
        </ul>
      
        <ul>
          <li><span class="yrsExp">17</span></li>
      
          <li>years of experience</li>
        </ul>
      
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-31
        • 1970-01-01
        相关资源
        最近更新 更多