MR Loll
MR Loll

Reputation: 41

jQuery animate number function. Want to turn it into Vanilla JavaScript

this function animates number inside an element to a defined number inside data-count value

How could I please do it in vanilla JavaScript

<div class="counter">
    <div class="row no-gutters">
        <div class="col-4">
            <div
                class="single-counter counter-color-1 d-flex align-items-center justify-content-center"
            >
                <div class="counter-items text-center">
                    <span id="count" data-count="175">0</span
                    ><span>K</span>
                    <p>Downloads</p>
                </div>
            </div>
        </div>
        <div class="col-4">
            <div
                class="single-counter counter-color-2 d-flex align-items-center justify-content-center"
            >
                <div class="counter-items text-center">
                    <span id="count" data-count="73">0</span
                    ><span>K</span>
                    <p>Active users</p>
                </div>
            </div>
        </div>
        <div class="col-4">
            <div
                class="single-counter counter-color-3 d-flex align-items-center justify-content-center"
            >
                <div class="counter-items text-center">
                    <span id="count" data-count="4.8">0</span>
                    <p>user rating</p>
                </div>
            </div>
        </div>
    </div>
    $('#count').each(function() {
        var counter = $(this),
            countTo = counter.attr('data-count');

        const countObj = { countNum: counter.text()}

        $(countObj).animate({
            countNum: countTo
        },{

            duration: 2000,
            easing:'linear',
            step: function() {

                counter.text(Math.floor(this.countNum));
            },
            complete: function() {
                counter.text(this.countNum);
            }

        });
    });


I tried this

countUp(elem) {
    var current = elem.innerHTML;
    var interval = setInterval(increase, 70);
    function increase() {
        elem.innerHTML = current++;
        if (current > elem.getAttribute("data-count")) {
            clearInterval(interval);
        }
    }
}

var span = document.querySelectorAll("#count");
var i = 0;
for (i; i < span.length; i++) {
    countUp(span[i]);
}

but it doesn't finish all elements animation at the same time; the elements which has the lower data-count value finishes earlier than the others that have higher data-count value

Upvotes: 0

Views: 597

Answers (1)

as-if-i-code
as-if-i-code

Reputation: 2360

element is not a selector in your case. Another issue is all <span> have duplicate id i.e. count
I have modified these duplicate ids to count1, count2, count3. And selector $('span[id^=count') in script below means all <span> elements which have id starting with word count

 $('span[id^=count').each(function() {
        var counter = $(this),
        countTo = counter.attr('data-count');

        const countObj = { countNum: counter.text()}

        $(countObj).animate({
                                countNum: countTo
                            },
                            {
                               duration: 2000,
                               easing:'linear',
                               step: function() {
                                         counter.text(Math.floor(this.countNum));
                                     },
                               complete: function() {
                                         counter.text(this.countNum);
                                     }

                         });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="counter">
  <div class="row no-gutters">
    <div class="col-4">
      <div class="single-counter counter-color-1 d-flex align-items-center justify-content-center">
        <div class="counter-items text-center">
          <span id="count1" data-count="175">0</span><span>K</span>
          <p>Downloads</p>
        </div>
      </div>
    </div>
    <div class="col-4">
      <div class="single-counter counter-color-2 d-flex align-items-center justify-content-center">
        <div class="counter-items text-center">
          <span id="count2" data-count="73">0</span><span>K</span>
          <p>Active users</p>
        </div>
      </div>
    </div>
    <div class="col-4">
      <div class="single-counter counter-color-3 d-flex align-items-center justify-content-center">
        <div class="counter-items text-center">
          <span id="count3" data-count="4.8">0</span>
          <p>user rating</p>
        </div>
      </div>
    </div>
  </div>

EDIT : Below is pure vanilla js function for you
You just need some basic maths to decide time interval for all elements

function countUp(elem) {
    var current = elem.innerHTML;

    // assume 2000(milliseconds) is time delay to complete all animations
    // determine time interval based on value of data-count
    var timeIntervalBeforeIncrement = 2000/elem.getAttribute("data-count")


    var interval = setInterval(increase, timeIntervalBeforeIncrement);
    function increase() {
        elem.innerHTML = current++;
        if (current > elem.getAttribute("data-count")) {
            clearInterval(interval);
        }
    }
}

var span = document.querySelectorAll("[id^='count']");


for (i = 0; i < span.length; i++) {
    countUp(span[i]);
}

Upvotes: 2

Related Questions