Alireza Behnamnik
Alireza Behnamnik

Reputation: 336

Start counting after scroll on specific element

I create a website and add a counter to my codes.

$(function() {
    function count($this){
        var current = parseInt($this.html(), 10);
        $this.html(++current);
        if(current !== $this.data('count')){
            setTimeout(function(){count($this)}, 50);
        }
    }        
  $(".c-section4").each(function() {
      $(this).data('count', parseInt($(this).html(), 10));
      $(this).html('0');
      count($(this));
  });
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<div class="section4">
<div class="section4-bg"></div>

<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>

<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>

<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>

</div>

Now i have a problem, i want to counter start when i scroll to this element

Demo

Sorry for my bad english

Upvotes: 6

Views: 15255

Answers (5)

Dane Iracleous
Dane Iracleous

Reputation: 1759

Here's my solution which supports floats and a configurable animation duration. It will only animate the count one time - as soon the element appears in the viewport of the specified container.

const initAnimatedCounts = () => {
  const ease = (n) => {
    // https://github.com/component/ease/blob/master/index.js
    return --n * n * n + 1;
  };
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        // Once this element is in view and starts animating, remove the observer,
        // because it should only animate once per page load.
        observer.unobserve(entry.target);
        const countToString = entry.target.getAttribute('data-countTo');
        const countTo = parseFloat(countToString);
        const duration = parseFloat(entry.target.getAttribute('data-animateDuration'));
        const countToParts = countToString.split('.');
        const precision = countToParts.length === 2 ? countToParts[1].length : 0;
        const startTime = performance.now();
        const step = (currentTime) => {
          const progress = Math.min(ease((currentTime  - startTime) / duration), 1);
          entry.target.textContent = (progress * countTo).toFixed(precision);
          if (progress < 1) {
            animationFrame = window.requestAnimationFrame(step);
          } else {
            window.cancelAnimationFrame(animationFrame);
          }
        };
        let animationFrame = window.requestAnimationFrame(step);
      }
    });
  });
  document.querySelectorAll('[data-animateDuration]').forEach((target) => {
    target.setAttribute('data-countTo', target.textContent);
    target.textContent = '0';
    observer.observe(target);
  });
};
initAnimatedCounts();
div {
  font-size: 30px;
  text-align: center;
  padding: 30px 0;
}
div > span {
  color: #003d82;
}
div.scrollpad {
  height: 100vh;
  background-color: #eee;
}
<div>
  <span>$<span data-animateDuration="1000">987.45</span></span> was spent on
  about <span><span data-animateDuration="1000">5.8</span>M</span> things.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
  There are <span><span data-animateDuration="1000">878</span>K</span> people involved.
  <br/>
  And <span><span data-animateDuration="1000">54</span></span> cakes.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
  Additionally, <span>$<span data-animateDuration="3000">300</span>B</span> went to waste.
  <br/>
  Because <span>$<span data-animateDuration="2000">54</span></span> was spent on each cake.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
  Lastly, <span><span data-animateDuration="4000">3.5334583</span>T</span> ants said hello.
  <br/>
  But <span><span data-animateDuration="2000">4</span></span> of them said goodbye.
</div>

Upvotes: 2

Martin Parenteau
Martin Parenteau

Reputation: 73731

You can handle the window scroll event and use the function given here by Scott Dowding to determine if the element has been scrolled into view. An isCounting flag can be set on each element to prevent counting several times simultaneously.

In the following code snippet, the counting is performed only while the element is visible.

$(function () {
    function isScrolledIntoView($elem) {
        var docViewTop = $(window).scrollTop();
        var docViewBottom = docViewTop + $(window).height();
        var elemTop = $elem.offset().top;
        var elemBottom = elemTop + $elem.height();
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }

    function count($this) {
        var current = parseInt($this.html(), 10);
        if (isScrolledIntoView($this) && !$this.data("isCounting") && current < $this.data('count')) {
            $this.html(++current);
            $this.data("isCounting", true);
            setTimeout(function () {
                $this.data("isCounting", false);
                count($this);
            }, 50);
        }
    }

    $(".c-section4").each(function () {
        $(this).data('count', parseInt($(this).html(), 10));
        $(this).html('0');
        $(this).data("isCounting", false);
    });

    function startCount() {
        $(".c-section4").each(function () {
            count($(this));
        });
    };

    $(window).scroll(function () {
        startCount();
    });

    startCount();
});
.tallDiv 
{
   height: 800px;
   background-color: silver;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>

<div class="section4">
  <div class="section4-bg"></div>
  <div class="tallDiv">Scroll down to test</div>
  <div class="counter-section">
    <span class="c-section4">152 </span>
    <h3> کارکنان ما </h3>
  </div>
  <div class="counter-section">
    <span class="c-section4">152 </span>
    <h3> کارکنان ما </h3>
  </div>
  <div class="counter-section">
    <span class="c-section4">152 </span>
    <h3> کارکنان ما </h3>
  </div>
  <div class="tallDiv"></div>
</div>

Upvotes: 8

MD Ashik
MD Ashik

Reputation: 9835

Live Link

You can use this Plugin for it. Source LINK

<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0'
 data-max='82' data-delay='19' data-increment="2">0</span>

NB: data-max='**'give your max-number and data-delay='**' select a time for countdown running and select increment data-increment="**" .

/**
* jQuery scroroller Plugin 1.0
*
* http://www.tinywall.net/
* 
* Developers: Arun David, Boobalan
* Copyright (c) 2014 
*/
(function($){
    $(window).on("load",function(){
        $(document).scrollzipInit();
        $(document).rollerInit();
    });
    $(window).on("load scroll resize", function(){
        $('.numscroller').scrollzip({
            showFunction    :   function() {
                                    numberRoller($(this).attr('data-slno'));
                                },
            wholeVisible    :     false,
        });
    });
    $.fn.scrollzipInit=function(){
        $('body').prepend("<div style='position:fixed;top:0px;left:0px;width:0;height:0;' id='scrollzipPoint'></div>" );
    };
    $.fn.rollerInit=function(){
        var i=0;
        $('.numscroller').each(function() {
            i++;
           $(this).attr('data-slno',i); 
           $(this).addClass("roller-title-number-"+i);
        });        
    };
    $.fn.scrollzip = function(options){
        var settings = $.extend({
            showFunction    : null,
            hideFunction    : null,
            showShift       : 0,
            wholeVisible    : false,
            hideShift       : 0,
        }, options);
        return this.each(function(i,obj){
            $(this).addClass('scrollzip');
            if ( $.isFunction( settings.showFunction ) ){
                if(
                    !$(this).hasClass('isShown')&&
                    ($(window).outerHeight()+$('#scrollzipPoint').offset().top-settings.showShift)>($(this).offset().top+((settings.wholeVisible)?$(this).outerHeight():0))&&
                    ($('#scrollzipPoint').offset().top+((settings.wholeVisible)?$(this).outerHeight():0))<($(this).outerHeight()+$(this).offset().top-settings.showShift)
                ){
                    $(this).addClass('isShown');
                    settings.showFunction.call( this );
                }
            }
            if ( $.isFunction( settings.hideFunction ) ){
                if(
                    $(this).hasClass('isShown')&&
                    (($(window).outerHeight()+$('#scrollzipPoint').offset().top-settings.hideShift)<($(this).offset().top+((settings.wholeVisible)?$(this).outerHeight():0))||
                    ($('#scrollzipPoint').offset().top+((settings.wholeVisible)?$(this).outerHeight():0))>($(this).outerHeight()+$(this).offset().top-settings.hideShift))
                ){
                    $(this).removeClass('isShown');
                    settings.hideFunction.call( this );
                }
            }
            return this;
        });
    };
    function numberRoller(slno){
            var min=$('.roller-title-number-'+slno).attr('data-min');
            var max=$('.roller-title-number-'+slno).attr('data-max');
            var timediff=$('.roller-title-number-'+slno).attr('data-delay');
            var increment=$('.roller-title-number-'+slno).attr('data-increment');
            var numdiff=max-min;
            var timeout=(timediff*1000)/numdiff;
            //if(numinc<10){
                //increment=Math.floor((timediff*1000)/10);
            //}//alert(increment);
            numberRoll(slno,min,max,increment,timeout);
            
    }
    function numberRoll(slno,min,max,increment,timeout){//alert(slno+"="+min+"="+max+"="+increment+"="+timeout);
        if(min<=max){
            $('.roller-title-number-'+slno).html(min);
            min=parseInt(min)+parseInt(increment);
            setTimeout(function(){numberRoll(eval(slno),eval(min),eval(max),eval(increment),eval(timeout))},timeout);
        }else{
            $('.roller-title-number-'+slno).html(max);
        }
    }
})(jQuery);
.nm {
	height: 400px;
	background: #f5f5f5;
	display: block;
}
.nm_1 {
	background-color: #632525;
}
.nm_2 {
	background-color: grad;
}
.nm_3 {
	background-color: gray;
}
.nm_4 {
	background-color: green;
}
.nm_5 {
	background-color: georgian;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="nm nm_1">
</section>
<section class="nm nm_2">
</section>
<section class="nm nm_3">
</section>
<section class="nm nm_4">
	
	<div>
		<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='192' data-delay='19' data-increment="2">0</span>
		<h3> کارکنان ما </h3>
	</div>
	<div>
		<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='282' data-delay='19' data-increment="2">0</span>
		<h3> کارکنان ما </h3>
	</div>
	<div>
		<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='82' data-delay='19' data-increment="2">0</span>
		<h3> کارکنان ما </h3>
	</div>
		
		
	
</section>
<section class="nm nm_4">
</section>
<section class="nm nm_5">
</section>

Upvotes: 3

srinivas.ln
srinivas.ln

Reputation: 309

Get the scroll Height and compare with the height of the start div(count start div) put a condition

$(function() {
  var pos = document.getElementById('targetId').scrollHeight;
  console.log(pos);
  
  if(pos>="75"){
  
    function count($this){
        var current = parseInt($this.html(), 10);
        $this.html(++current);
        if(current !== $this.data('count')){
            setTimeout(function(){count($this)}, 50);
        }
    }        
  $(".c-section4").each(function() {
      $(this).data('count', parseInt($(this).html(), 10));
      $(this).html('0');
      count($(this));
  });
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>



<div class="counter-section" id="targetId">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>

Upvotes: 3

edlerd
edlerd

Reputation: 2145

You need to give the target element and id, then get its postition from top var pos = document.getElementById('targetId').scrollHeight - element.clientHeight; and compare it to the scrolled height window.pageYOffset.

If widow offset is greater than the pos, you can start the counter. You should hook the comparison to the window.onscroll event.

Also you should memorize in a variable if you started the counter for an element already to avoid starting it twice.

Upvotes: 3

Related Questions