'How to set up the counter when it is detected
In my project, there should be a counter. I have used the "reveal function". I want the counter to start when it goes to "reveal function". And when the bottom-up scrolling is done again, the "reveal function" will be performed again. Given that I used the "reveal function", but when the scroll moves from bottom to top, the counter does not start again. In the code I wrote, the counter runs when the page loads and the "reveal function" has no effect.
How can I solve this problem? Thanks in advance for your guidance.
//counter
const counter = (EL) => {
const duration = 4000; // Animate all counters equally for a better UX
const start = parseInt(EL.textContent, 10); // Get start and end values
const end = parseInt(EL.dataset.counter, 10); // PS: Use always the radix 10!
if (start === end) return; // If equal values, stop here.
const range = end - start; // Get the range
let curr = start; // Set current at start position
const loop = (raf) => {
if (raf > duration) raf = duration; // Stop the loop
const frac = raf / duration; // Get the time fraction
const step = frac * range; // Calculate the value step
curr = start + step; // Increment or Decrement current value
EL.textContent = parseInt(curr, 10); // Apply to UI as integer
if (raf < duration) requestAnimationFrame(loop); // Loop
};
requestAnimationFrame(loop); // Start the loop!
};
document.querySelectorAll("[data-counter]").forEach(counter);
//counter
// reveal
function reveal() {
var reveals = document.querySelectorAll(".reveal");
for (var i = 0; i < reveals.length; i++) {
var windowHeight = window.innerHeight;
var elementTop = reveals[i].getBoundingClientRect().top;
var elementVisible = 10;
if (elementTop < windowHeight - elementVisible) {
reveals[i].classList.add("active");
} else {
reveals[i].classList.remove("active");
}
}
}
window.addEventListener("scroll", reveal);
// reveal
.container{
overflow-y: scroll;
}
.pre-reveal{
width: 100%;
height: 80vh;
border: 1px solid red;
}
/* reveal */
.reveal {
border: 1px solid green;
position: relative;
opacity: 0;
margin-top: 1rem;
}
.reveal.active {
opacity: 1;
}
/* reveal */
<div class="container">
<div class="pre-reveal"></div>
<div class="reveal">
<span>A: </span>
<span data-counter="10">0</span>
<br>
<span>B: </span>
<span data-counter="2022">1000</span>
<br>
<span>C: </span>
<span data-counter="0">9999</span>
<br>
<span>D: </span>
<span data-counter="-1000">1000</span>
<br>
<span>E: </span>
<span data-counter="666">0</span>
<br>
</div>
</div>
Solution 1:[1]
How to manage the counter with javascript
const counter = (EL) => {
const duration = 10000;
const start = parseInt(EL.textContent, 10);
const end = parseInt(EL.dataset.counter, 10);
if (start === end) return;
const range = end - start;
let curr = start;
let curRaf = null;
const loop = (raf) => {
if (!curRaf) curRaf = raf;
let offsetRaf = raf - curRaf;
if (offsetRaf > duration) offsetRaf = duration;
const frac = offsetRaf / duration;
const step = frac * range;
curr = start + step;
EL.textContent = parseInt(curr, 10);
if (offsetRaf < duration) requestAnimationFrame(loop); p
};
requestAnimationFrame(loop);
};
var hasTriggers = false;
window.addEventListener('scroll', function() {
let heightScroll = document.body.scrollTop || document.documentElement.scrollTop;
let height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
let scroll = Math.round((heightScroll / height) * 100);
console.log(scroll);
if (scroll > 14 && scroll < 17) {
if (!hasTriggers) document.querySelectorAll("[data-counter]").forEach(counter);
hasTriggers = true;
}
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | h.m.p.biologist_programmer |