I'm using a script to count numbers from 0 to their actual value. To start the counter, I want the element to be in the visible area of the viewport.
I found a solution to check if an element is in the visible area.
But that doesn't work if I'm using more than one number elemt on different areas of the page. It counts every element with the same class (.counter
).
If I use the counter script twice with a different name, the second version doesn't work and the first one doesn't work on scroll. Only if I have the counter in the visible area on pageload.
Here's my counter code:
$('.counter').each(function() {
var $this = $(this),
countTo = $this.attr('data-count');
$({ countNum: $this.text()}).animate({
countNum: countTo
},
{
duration: 2000,
easing:'linear',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
}
});
});
And this is the solution I tried (and it works once per page): https://stackoverflow.com/a/488073/1788961
Here you find a fiddle with the whole code: https://codepen.io/cray_code/pen/QYXVWL
This is the code to check if I scroll to the element (see linked answer above):
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 Utils() {
}
Utils.prototype = {
constructor: Utils,
isElementInView: function (element, fullyInView) {
var pageTop = $(window).scrollTop();
var pageBottom = pageTop + $(window).height();
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {
return ((pageTop < elementTop) && (pageBottom > elementBottom));
} else {
return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
}
}
};
var Utils = new Utils();
You check isElementInView once instead of for each element individually. Of course it starts all counters.
var isElementInView = Utils.isElementInView($('.counter'), false);
if (isElementInView) {
$('.counter').each(function() {
Move it inside your .each
function and it will work for each counter separately.
$('.counter').each(function() {
var $this = $(this),
countTo = $this.attr('data-count');
var isElementInView = Utils.isElementInView($this, false);
if (isElementInView) {
// do animation
If you want that to happen when you scroll you need to add an EventListener to the page that executes the code everytime you scroll: https://developer.mozilla.org/en-US/docs/Web/Events/scroll
function checkForVisible(){
$('.counter').each(function() {
var $this = $(this),
countTo = $this.attr('data-count');
var isElementInView = Utils.isElementInView($this, false);
if (isElementInView) {
// etc code
}
var ticking = false;
window.addEventListener('scroll', function(e) {
if (!ticking) {
window.requestAnimationFrame(function() {
checkForVisible();
ticking = false;
});
ticking = true;
}
});