Animated number counter on view

Hello, I am using the code below to create an animated number counter:

$w.onReady(function () {});
let startNum = 0;let endNum = 40;const duration =  50; 
$w.onReady(function () {setInterval(()=> {countUp();}, duration);});function countUp(){if (startNum <= endNum ){$w('#text53').text = startNum.toString();
        startNum++;}}

let startNum1 = 0;let endNum1 = 10;const duration1 =  200; 
$w.onReady(function () {setInterval(()=> {countUp1();}, duration1);});function countUp1(){if (startNum1 <= endNum1 ){$w('#text53DAC113').text = startNum1.toString();
        startNum1++;}
}

But it loads as soon as the page loads, how can I make it load when it’s seen on the screen + play the animation only once? I tried to move it in an onViewportEnter but couldn’t make it work. Also, the text appears thin despite I made it bold.

You could try to create a container box and attach text53 to it. Then try to call the animation when the container box is in the viewport.

Ok, so your code is a little bit messy. You have three $w.onReady() methods being called, and you only have to have one, that executes the code after the page is loaded. As you want to wait for the page to load completely before starting the count, you need to check the rendered property of the element you want rendered.

You also need to store the intervals in a variable, so you can call a clearInterval() method to stop the counter as soon as startNum is equal or bigger than endNum .

Something like this:

let startNum = 0
let endNum = 40
const duration = 50
let startNum1 = 0
let endNum1 = 10
const duration1 = 200
let counter1
let counter2

$w.onReady(function () {
  if ($w('#text53').rendered) {
    counter1 = setInterval(() => countUp(), duration)
  }
  if ($w('#text53DAC113').rendered) {
    counter2 = setInterval(() => countUp1(), duration1)
  }
})

function countUp() {
  $w('#text53').text = startNum.toString()
  startNum++
  if (startNum >= endNum) clearInterval(counter1)
}

function countUp1() {
  $w('#text53DAC113').text = startNum1.toString()
  startNum1++
  if (startNum1 >= endNum1) clearInterval(counter2)
}

Thank you for the detailed reply, it really helped me out. What I am trying to do is not actually start the counter after the page loads, but after the counter is visible on the screen (since it’s not on top of the page but downwards). So I figured if I put the code in an onViewportEnter it does work. I am a beginner with Velo so your reply really helped me a lot, thanks!

Final code with automated comments for others with the same problem:

// API Reference: https://www.wix.com/velo/reference/api-overview/introduction
// “Hello, World!” Example: https://learn-code.wix.com/en/article/1-hello-world

$w.onReady(function () {
    // Write your JavaScript here

    // To select an element by ID use: $w('#elementID')

    // Click 'Preview' to run your code
});

/**
*   Adds an event handler that runs when an element is displayed
 in the viewable part of the current window.
    [Read more](https://www.wix.com/corvid/reference/$w.ViewportMixin.html#onViewportEnter)
*    @param {$w.Event} countnumbers
*/
export function text53_viewportEnter(countnumbers) {
    // This function was added from the Properties & Events panel. To learn more, visit http://wix.to/UcBnC-4
    // Add your code for this event here:
     let startNum = 0
let endNum = 40
const duration = 50
let startNum1 = 0
let endNum1 = 10
const duration1 = 200
let counter1
let counter2

$w.onReady(function () {
  if ($w('#text53').rendered) {
    counter1 = setInterval(() => countUp(), duration)
  }
  if ($w('#text53DAC113').rendered) {
    counter2 = setInterval(() => countUp1(), duration1)
  }
})

function countUp() {
  $w('#text53').text = startNum.toString()
  startNum++
  if (startNum >= endNum) clearInterval(counter1)
}

function countUp1() {
  $w('#text53DAC113').text = startNum1.toString()
  startNum1++
  if (startNum1 >= endNum1) clearInterval(counter2)
}
}

Thanks!

@avocado although your code is working, it is still doing things wrong.

Try refactoring your code to this:

let startNum = 0
let endNum = 40
const duration = 50
let startNum1 = 0
let endNum1 = 10
const duration1 = 200
let counter1
let counter2

$w.onReady(function () {})

export function text53_viewportEnter(countnumbers) {
  counter1 = setInterval(() => countUp(), duration)
  counter2 = setInterval(() => countUp1(), duration1)
}

function countUp() {
  $w('#text53').text = startNum.toString()
  startNum++
  if (startNum >= endNum) clearInterval(counter1)
}

function countUp1() {
  $w('#text53DAC113').text = startNum1.toString()
  startNum1++
  if (startNum1 >= endNum1) clearInterval(counter2)
}