4

I have a simple jQuery code that works perfectly (and I would like to keep). The problem is that this animation is in a section below on page and it starts running when the page loads. I need this animation (numbers start at 0 and run until the number I put in the divs) to happen only when the user scroll and reaches that div. I searched on google and here on StackOverflow but the solutions that I found didn't work or required a plugin (which I don't wanna use).

Here's the Demo code that I have until the moment: https://jsfiddle.net/aj7Lk2bw/2/

the jQuery is:

    $('.value').each(function () {
    $(this).prop('Counter',0).animate({
        Counter: $(this).text()
    }, {
        duration: 4000,
        easing: 'swing',
        step: function (now) {
            $(this).text(Math.ceil(now));
        }
    });
});
Jorge
  • 201
  • 2
  • 3
  • 14
  • I suppose you need onscroll event and check some positions. If your elements appear in `window` - you can fire countdown. – u_mulder Mar 13 '18 at 15:37
  • A question to look https://stackoverflow.com/questions/3045852/triggering-jquery-event-when-an-element-appears-on-screen – u_mulder Mar 13 '18 at 15:39

3 Answers3

9

See if this is what you want: https://jsfiddle.net/aj7Lk2bw/19/

$(window).scroll(testScroll);
var viewed = false;

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 testScroll() {
  if (isScrolledIntoView($(".numbers")) && !viewed) {
      viewed = true;
      $('.value').each(function () {
      $(this).prop('Counter',0).animate({
          Counter: $(this).text()
      }, {
          duration: 4000,
          easing: 'swing',
          step: function (now) {
              $(this).text(Math.ceil(now));
          }
      });
    });
  }
}

Found the way to do it here: Run script when div is visible in browser window

Zé Cláudio
  • 231
  • 1
  • 5
  • Hi ! this is almost the perfect one. The only problem is that the numbers after counting up, they start to count backward to 1 hehe. I need the numbers to start counting from 0 until the desired value and stop at this value. – Jorge Mar 13 '18 at 16:13
  • Hi Ze Claudio! Your solution works perfectly, thank you really much and sorry the delay to answer you back. – Jorge Mar 13 '18 at 21:41
4

This is a possible solution:

var section = document.querySelector('.numbers');
var hasEntered = false;

window.addEventListener('scroll', (e) => {
    var shouldAnimate = (window.scrollY + window.innerHeight) >= section.offsetTop;

    if (shouldAnimate && !hasEntered) {
    hasEntered = true;

    $('.value').each(function () {
        $(this).prop('Counter',0).animate({
        Counter: $(this).text()
        }, {
        duration: 4000,
        easing: 'swing',
        step: function (now) {
            $(this).text(Math.ceil(now));
        }
        });
    });

  }
});

the variable section is your blue section with the numbers, hasEntered is to not repeat the animation.

If the window scroll is higher than the section position, than it will animate!

Fiddle: https://jsfiddle.net/aj7Lk2bw/18/

0

Here I can share another example.

You can try that HTML:

$(window).scroll(testScroll);
var viewed = false;

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 testScroll() {
  if (isScrolledIntoView($(".number")) && !viewed) {
      viewed = true;
      $('.value').each(function () {
      $(this).prop('Counter',0).animate({
          Counter: $(this).text()
      }, {
          duration: 4000,
          easing: 'swing',
          step: function (now) {
              $(this).text(Math.ceil(now));
          }
      });
    });
  }
}
<div class="number">
                    
                             <div class="value-wrap">
                    <div class="value" akhi="">51</div>
                    <h4>YEARS IN BUSINESS</h4>
                </div>
               
                             <div class="value-wrap">
                    <div class="value" akhi="">29</div>
                    <h4>WORLDWIDE CERTIFICATION</h4>
                </div>
               
                             <div class="value-wrap">
                    <div class="value" akhi="">58</div>
                    <h4>COUNTRIES REPRESENTED</h4>
                </div>
               
                             <div class="value-wrap">
                    <div class="value" akhi="">6</div>
                    <h4>CONTINENT REPRESENTED</h4>
                </div>
  </div>