【问题标题】:Loop Through jQuery Elements Separately and Animate on Page Scroll分别循环遍历 jQuery 元素并在页面滚动时设置动画
【发布时间】:2017-11-17 17:52:49
【问题描述】:

我已经设法让一个简单的统计计数器从零运行到给定值,它只在页面滚动时激活,但这并不完全符合我的目标。

问题是,所有的“.counter”元素都会在第一个元素出现时同时触发,而不是等到每个单独的元素在屏幕上真正可见。因此,一旦窗口点击包含 div,它们就会立即关闭。

我想让每个单独的 .counter 等到它完全可见后再触发。

这是我目前所得到的:

HTML:

<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div id="stats">
  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="400"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="350"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="12"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="97"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="899"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="4"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="0"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>

  <div class="single-stat">
    <h6 class="top-line">title</h6>
    <div class="stat-container">
      <h6 class="stat"><span class="counter" count="6"></span></h6>
    </div>
    <h6 class="bottom-line">bottom line</h6>
  </div>
</div>

还有 jQuery...

    (function($) {

  $(function() {

    var $counters = $('.counter'); //contains all elements of counter class

    var $window = $(window);

    $window.on('scroll', function(e) {
      $counters.each(function(i, elem) { //loop through each element
        if ($(this).hasClass('counted')) // check if already animated
          return;
        animateCounter($(this));
      });
    });
  });

  function animateCounter(elem) {
    var winTop = $(window).scrollTop(); // calculate distance from top of window
    var winBottom = winTop + $(window).height();
    var elemTop = $(elem).offset().top; // element distance from top of page
    var elemBottom = elemTop + $(elem).height();

    if ((elemBottom <= winBottom) && (elemTop >= winTop)) {
      $('.counter').each(function() {
        var $this = $(this);
        jQuery({
          Counter: 0
        }).animate({
          Counter: $this.attr('count')
        }, {
          duration: 3000,
          step: function() {
            $this.text(Math.ceil(this.Counter));
          }
        });
        $this.removeClass('counter').addClass('counted');
      });
    }
  }
})(jQuery);

在这里提琴: https://jsfiddle.net/ahfL4jxr/11/

提前致谢。

【问题讨论】:

  • 问题是(我认为)$(this) 是所有 .counter 元素,并且由于它是一个类选择器,因此它将为所有人运行。我会尝试一下,看看我能不能解决它。
  • 字面意思是一个变化:)。已在我的回答中修复

标签: javascript jquery html css


【解决方案1】:

啊,你好亲密。

您的目标是所有元素,而不是您推动的论点中的元素。

在您的 animateCounter() 函数中,$('.counter') 应更改为 $(elem)

https://jsfiddle.net/7xsv33hf/

【讨论】:

    【解决方案2】:

    您的代码的问题在于您正确地检查了滚动距离,但将动画应用于所有计数器。

    	(function($) {
      
    	  $(function() {
        
    	    var $counters = $('.counter'); //contains all elements of counter class
          
    	    var $window = $(window);
          
    	    $window.on('scroll', function(e) {
    	      $counters.each(function(i, elem) { //loop through each element
    	        if ($(this).hasClass('counted')) // check if already animated
    	          return;
    	        animateCounter($(this));
    	      });
    	    });
    	  });
        
    	  function animateCounter(elem) {
    	    var winTop = $(window).scrollTop(); // calculate distance from top of window
    	    var winBottom = winTop + $(window).height();
    	    var elemTop = $(elem).offset().top; // element distance from top of page
    	    var elemBottom = elemTop + $(elem).height();
          
    	    if ((elemBottom <= winBottom) && (elemTop >= winTop)) {
    	        var $this = elem;
    	        jQuery({
    	          Counter: 0
    	        }).animate({
    	          Counter: $this.attr('count')
    	        }, {
    	          duration: 3000,
    	          step: function() {
    	            $this.text(Math.ceil(this.Counter));
    	          }
    	        });
    	        $this.removeClass('counter').addClass('counted');
    	      
    	    }
    	  }
    	})(jQuery);
    #stats {
      font-size: 0;
    }
    
    #stats * {
      color: #000;
    }
    
    .single-stat {
      width: 45%;
      margin: 2.5%;
      display: inline-block;
      vertical-align: top;
      text-align: center;
    }
    
    .stat-container {
      position: relative;
    }
    
    .top-line {
      font-size: 30px;
      color: red;
    }
    
    .stat {
      font-size: 48px;
      margin: 0;
    }
    
    .bottom-line {
      font-size: 16px;
    }
    
    .animateBlock {
      display: inline-block;
      position: relative;
    }
    
    .animateBlock {
      opacity: 0;
    }
    
    .left.animated {
      transform: translateX(-40px);
    }
    
    .right.animated {
      transform: translateX(40px);
    }
    
    .top.animated {
      transform: translateY(-40px);
    }
    
    .bottom.animated {
      transform: translateY(40px);
    }
    
    .animated {
      animation: come-in 0.5s ease forwards;
    }
    
    @keyframes come-in {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
        transform: translateY(0);
        transform: translateX(0);
      }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    <div id="stats">
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="400"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="350"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="12"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="97"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="899"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="4"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="0"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    
      <div class="single-stat">
        <h6 class="top-line">title</h6>
        <div class="stat-container">
          <h6 class="stat"><span class="counter" count="6"></span></h6>
        </div>
        <h6 class="bottom-line">bottom line</h6>
      </div>
    </div>

    https://jsfiddle.net/cndbqeck/

    【讨论】:

      【解决方案3】:

      在 animateCounter() 函数中,您的 javascript 中有错误,您执行了不必要的 foreach,因为在函数中您已经传递了调用时需要动画的元素。

      (function($) {
      
        $(function() {
      
          var $counters = $('.counter'); //contains all elements of counter class
      
          var $window = $(window);
      
          $window.on('scroll', function(e) {
            $counters.each(function(i, elem) { //loop through each element
              if ($(this).hasClass('counted')) // check if already animated
                return;
              animateCounter($(this));
            });
          });
        });
      
        function animateCounter(elem) {
          var winTop = $(window).scrollTop(); // calculate distance from top of window
          var winBottom = winTop + $(window).height();
          var elemTop = $(elem).offset().top; // element distance from top of page
          var elemBottom = elemTop + $(elem).height();
      
          if ((elemBottom <= winBottom) && (elemTop >= winTop)) {
            var $this = $(elem);
            jQuery({
              Counter: 0
            }).animate({
              Counter: $this.attr('count')
            }, {
              duration: 3000,
              step: function() {
                $this.text(Math.ceil(this.Counter));
              }
            });
            $this.removeClass('counter').addClass('counted');
          }
        }
      })(jQuery);
      #stats {
        font-size: 0;
      }
      
      #stats * {
        color: #000;
      }
      
      .single-stat {
        width: 45%;
        margin: 2.5%;
        display: inline-block;
        vertical-align: top;
        text-align: center;
      }
      
      .stat-container {
        position: relative;
      }
      
      .top-line {
        font-size: 30px;
        color: red;
      }
      
      .stat {
        font-size: 48px;
        margin: 0;
      }
      
      .bottom-line {
        font-size: 16px;
      }
      
      .animateBlock {
        display: inline-block;
        position: relative;
      }
      
      .animateBlock {
        opacity: 0;
      }
      
      .left.animated {
        transform: translateX(-40px);
      }
      
      .right.animated {
        transform: translateX(40px);
      }
      
      .top.animated {
        transform: translateY(-40px);
      }
      
      .bottom.animated {
        transform: translateY(40px);
      }
      
      .animated {
        animation: come-in 0.5s ease forwards;
      }
      
      @keyframes come-in {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
          transform: translateY(0);
          transform: translateX(0);
        }
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <p>&nbsp;</p>
      <div id="stats">
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="400"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="350"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="12"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="97"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="899"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="4"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="0"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      
        <div class="single-stat">
          <h6 class="top-line">title</h6>
          <div class="stat-container">
            <h6 class="stat"><span class="counter" count="6"></span></h6>
          </div>
          <h6 class="bottom-line">bottom line</h6>
        </div>
      </div>

      【讨论】:

        猜你喜欢
        • 2013-09-27
        • 2015-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        相关资源
        最近更新 更多