1

I need your help because I've been on a project for hours and can't make any headway. An "animated" counter is to be installed on our website. This shows, for example, the monthly cost savings. The following code works great so far.

    <script>
/* <![CDATA[ */
var ersparnis = 4600;

var inv = setInterval(function() {     
    if(ersparnis < 4800)
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    else
        clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
    + <span id="counter_ersparnis"></span> €
</h2>

But now I want the Javascript to start only when the user scrolls to the relevant point. I have now tried to do this with a jQuery code from the Internet, but without success!

<script>
/* <![CDATA[ */
jQuery.fn.isOnScreen = function()
{
 var win = jQuery(window);
 var viewport = {
  top : win.scrollTop(),
  left : win.scrollLeft()
 };
 viewport.right = viewport.left + win.width();
 viewport.bottom = viewport.top + win.height();
 var bounds = this.offset();
 bounds.right = bounds.left + this.outerWidth();
 bounds.bottom = bounds.top + this.outerHeight();
 return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};

jQuery(window).scroll(function()
{
 if(jQuery('#element').isOnScreen())
 {
var ersparnis = 4600;

var inv = setInterval(function() {     
    if(ersparnis < 4800)
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    else
        clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
    + <span id="counter_ersparnis"></span> €
</h2>
 } }

By the way, the whole thing should be implemented on a Jimdo site, so I also added the database with the following code in the head area.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>

You might hear it already, I'm not really familiar with CSS / HTML and Javascript. So it would be great if someone could offer me a plug and play solution. I usually get it rewritten, but not tinkered together (because I want three of these counters next to each other.

1
  • Have you tried to replace #element with the actual id #counter_ersparnis?
    – user6749601
    Commented Apr 5, 2021 at 8:56

2 Answers 2

1

Try This im not a big proponent of jquery so its plain JavaScript.

const targetElement = document.querySelector('#element');
let isCounting = false;
var inv;

document.addEventListener('scroll', function(e) {
    const bounding = targetElement.getBoundingClientRect();
    
    if (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
    ) {
        if(!isCounting ){
        var ersparnis = 4600;

        inv = setInterval(function() {     
            document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
        }, 500 / 100);
        isCounting = true;
        }
    }else{
        isCounting = false;
        clearInterval(inv);
    }
});

To make the code a bit cleaner and reuseable you could do this.

const targetElement = document.querySelector('#element');
let isCounting = false;
let inv;

const isVisible = function (elem) {
    var bounding = elem.getBoundingClientRect();
    return (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
};

function startCounter(){
    var ersparnis = 4600;

    inv = setInterval(function() {     
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    }, 500 / 100);

    isCounting = true;

}

function stopCounter(){

    clearInterval(inv);
    isCounting = false;
    
}

document.addEventListener('scroll', function(e) {
    const visible = isVisible( targetElement );
    if( visible && !isCounting ){
        startCounter();
    }else if( !visible && isCounting ){
        stopCounter();
    }
});

1
  • Thanks for the fast respond. Both codes can be implemented, but they are both without function. It just shows me the currency symbol instead of the numbers. Strangely enough, the two counters no longer work when I insert this script, although all three are individually defined. So e.g. counter_saving, counter_sparquote and counter_kosten. Commented Apr 5, 2021 at 18:11
1

You can use Intersection Observer API to observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport:

let options = {
  root: null, //--> viewport if it is null
  rootMargin: '0px',
  threshold: 1.0
}

const callback = function(entries, observer) {
  entries.forEach(entry => {
    let ersparnis = 4600;
    const inv = setInterval(function() {
      if (ersparnis < 4800)
        entry.target.innerHTML = ++ersparnis;
      else
        clearInterval(inv);
    }, 500 / 100);
  });
};

let observer = new IntersectionObserver(callback, options);

const target = document.querySelector('#counter_ersparnis');
observer.observe(target);
2
  • Thanks for the answer. Unfortunately I don't get that implemented for me. How do I have to change it so that it also outputs the text in h2, like with my previous code? Commented Apr 5, 2021 at 18:10
  • @D.Fuchs1996 See this working example, stackblitz.com/edit/js-tjzhkx?file=index.html, you can disconnect the observer, also you can check if the node it is not visible to stop the interval..etc
    – lissettdm
    Commented Apr 5, 2021 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.