Viewport Counter Animation

User
jQuery(document).ready(function($) {
$('.elementor-counter-number').css('opacity', 0); // Hide numbers initially
$('.elementor-counter').each(function(index) {
var counter = $(this);
var countTo = parseFloat(counter.find('.elementor-counter-number').data('to-value')); // Get the target value as a float
var hasDecimals = countTo % 1 !== 0; // Check if the number has decimals
counter.find('.elementor-counter-number').text(0); // Set the initial count to zero

// Start counting with a delay
setTimeout(function() {
counter.find('.elementor-counter-number').css('opacity', 1); // Make the number visible
$({ countNum: 0 }).animate({ countNum: countTo }, {
duration: 2000, // Duration for counting
easing: 'linear',
step: function() {
// Display the number with or without decimals
counter.find('.elementor-counter-number').text(
hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
);
},
complete: function() {
// Ensure it shows the final value with or without decimals
counter.find('.elementor-counter-number').text(
hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
);
}
});
}, index * 1500); // Delay between each counter
});
});
run elementor counter when in viewport

Assistant
To ensure that the Elementor counter only starts animating when it enters the viewport, you can use the `Intersection Observer` API or a jQuery plugin like `waypoints`. Below is an updated version of your script using the `Intersection Observer` API:

### Updated Script:

jQuery(document).ready(function($) {
    function animateCounter(counter) {
        var countTo = parseFloat(counter.find('.elementor-counter-number').data('to-value')); // Get the target value as a float
        var hasDecimals = countTo % 1 !== 0; // Check if the number has decimals
        counter.find('.elementor-counter-number').text(0); // Set the initial count to zero

        $({ countNum: 0 }).animate({ countNum: countTo }, {
            duration: 2000, // Duration for counting
            easing: 'linear',
            step: function() {
                // Display the number with or without decimals
                counter.find('.elementor-counter-number').text(
                    hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
                );
            },
            complete: function() {
                // Ensure it shows the final value with or without decimals
                counter.find('.elementor-counter-number').text(
                    hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
                );
            }
        });
    }

    var counters = $('.elementor-counter');

    // Hide counters initially
    counters.find('.elementor-counter-number').css('opacity', 0);

    // Use Intersection Observer to trigger animation when in viewport
    var observer = new IntersectionObserver(function(entries) {
        entries.forEach(function(entry) {
            if (entry.isIntersecting) {
                var counter = $(entry.target);
                counter.find('.elementor-counter-number').css('opacity', 1); // Make number visible
                animateCounter(counter); // Animate the counter
                observer.unobserve(entry.target); // Stop observing once animated
            }
        });
    }, { threshold: 0.5 }); // Trigger when 50% of the element is in viewport

    // Observe each counter
    counters.each(function() {
        observer.observe(this);
    });
});

### Explanation:
1. **Intersection Observer**:
– Detects when each `.elementor-counter` enters the viewport.
– Triggers the animation only once per counter.
– Stops observing after the animation is triggered, improving performance.

2. **Animation Logic**:
– The `animateCounter` function animates the number counting up to its target value.

3. **Threshold**:
– Set to `0.5` (50%) to start the animation when half the counter is visible.

4. **Improved Performance**:
– Observes elements efficiently without continuously polling or relying on scroll events.

This script will work seamlessly for animating Elementor counters only when they are visible in the viewport.

User
also add setTimeout(function() {
Assistant
Here's the updated script incorporating a `setTimeout` function to introduce a delay before the counter starts animating when it enters the viewport:

### Updated Script with `setTimeout`:

jQuery(document).ready(function($) {
    function animateCounter(counter) {
        var countTo = parseFloat(counter.find('.elementor-counter-number').data('to-value')); // Get the target value as a float
        var hasDecimals = countTo % 1 !== 0; // Check if the number has decimals
        counter.find('.elementor-counter-number').text(0); // Set the initial count to zero

        $({ countNum: 0 }).animate({ countNum: countTo }, {
            duration: 2000, // Duration for counting
            easing: 'linear',
            step: function() {
                // Display the number with or without decimals
                counter.find('.elementor-counter-number').text(
                    hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
                );
            },
            complete: function() {
                // Ensure it shows the final value with or without decimals
                counter.find('.elementor-counter-number').text(
                    hasDecimals ? this.countNum.toFixed(2) : Math.floor(this.countNum)
                );
            }
        });
    }

    var counters = $('.elementor-counter');

    // Hide counters initially
    counters.find('.elementor-counter-number').css('opacity', 0);

    // Use Intersection Observer to trigger animation when in viewport
    var observer = new IntersectionObserver(function(entries) {
        entries.forEach(function(entry) {
            if (entry.isIntersecting) {
                var counter = $(entry.target);
                setTimeout(function() { // Delay before starting the animation
                    counter.find('.elementor-counter-number').css('opacity', 1); // Make number visible
                    animateCounter(counter); // Animate the counter
                }, 500); // 500ms delay before the animation starts
                observer.unobserve(entry.target); // Stop observing once animated
            }
        });
    }, { threshold: 0.5 }); // Trigger when 50% of the element is in viewport

    // Observe each counter
    counters.each(function() {
        observer.observe(this);
    });
});

### Changes Made:
1. **`setTimeout` Added**:
– Introduces a 500ms delay (adjustable) before the animation starts when a counter enters the viewport.

2. **Placement**:
– Wrapped the `animateCounter` call inside `setTimeout` to delay the animation execution.

3. **Visibility Adjustment**:
– The counter's number is made visible (`opacity: 1`) before the animation begins after the delay.

### Key Points:
– **Delay Duration**: You can adjust the `500` milliseconds in `setTimeout` to control the delay for each counter.
– **Intersection Observer**: Continues to ensure that the animation is triggered only when the counter is visible in the viewport.

This script provides a smooth and visually appealing delay for the counter animations, enhancing the user experience.

Leave a Comment

Your email address will not be published. Required fields are marked *