循环遍历jQuery元素并在页面滚动上进行动画处理

时间:2017-11-17 09:32:28

标签: javascript jquery html css

我设法让一个简单的统计计数器从零运行到一个给定的值,它只在页面滚动时激活,但它并不像我的目标那样。< / p>

问题是,所有的&#34; .counter&#34;一旦第一个元素进入视图,元素就会同时触发,而不是等到每个单独的元素在屏幕上实际可见。因此,当窗口撞到包含的div时,所有这些都立刻就会消失。

我希望让每个人都在等待,直到它在它发射之前完全可见。

这是我到目前为止所得到的:

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/

提前致谢。

3 个答案:

答案 0 :(得分:1)

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

	(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/

答案 1 :(得分:1)

啊,你太近了。

您定位所有元素,而不是您推送的参数中的元素。

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

https://jsfiddle.net/7xsv33hf/

答案 2 :(得分:0)

你的javascript在animateCounter()函数中有一个错误,你做了一个不必要的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>