javascripthtmljquerycssodometer

How to make odometer scrolling numbers on hover


I have the odometer js implemented on the stats of the website I have. The animation for the stats is already there. when you scroll down it looks good and is animated, but then it plays once and stops.

I want to repeat the scroll effect on each number individually every time someone hovers. Can anyone help me with this? Your help on this will be hearty appreciate.

(function($) {
  $(document).ready(function() {
    //Odometer number rolling
    window.onload = function() {
      setTimeout(function() {
        const odometerElements = document.querySelectorAll('.odometer');
        odometerElements.forEach((element) => {
          const targetValue = element.getAttribute('data-value');
          const odometer = new Odometer({
            el: element,
            value: 0,
            format: '(,ddd)',
            duration: 18000,
          });
          odometer.update(targetValue);
        });
      }, 150);
    };
})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<section class="company-statistics">
  <div class="container">
    <div class="stats-wrapper">
      <div class="stats-content row">
        <div class="col-6 col-md-4 col-lg-4 stat-item">
          <div class="odometer" data-value="13">0</div>
        </div>
        <div class="col-6 col-md-4 col-lg-4 stat-item">
          <div class="odometer" data-value="10">0</div>
        </div>
        <div class="col-6 col-md-4 col-lg-4 stat-item">
          <div class="odometer" data-value="75">0</div>
        </div>
        <div class="col-6 col-md-4 col-lg-4 stat-item">
          <div class="odometer" data-value="18">0</div>
        </div>
        <div class="col-6 col-md-4 col-lg-4 stat-item">
          <div class="odometer" data-value="22">0</div>
        </div>
        <div class="col-6 col-md-4 col-lg-4 d-xl-none stat-item">
          <div class="odometer" data-value="45">0</div>
        </div>
      </div>
    </div>
  </div>
</section>


Solution

  • To get the odometer rolling create a function odo_roll() and run it on hover with

    $(".odometer").hover(function() {
       odo_roll();
    });
    

    But since the odometer will only roll if its value is not the target value, you need to somehow change the initial value. Random numbers seem a good choice:

    odometer.update(rnd(10, 99));
    

    What might also be causing trouble in your code is the fact that it's using window.onload after $(document).ready() but when the DOM is ready the window.onload event has already fired.

    See https://api.jquery.com/ready/

    Quote:

    Although handlers added by .ready() will always be executed in a dynamically loaded script, the window's load event has already occurred and those listeners will never run.

    Working demo

    function rnd(minVal, maxVal) {
      var randVal = minVal + (Math.random() * (maxVal - minVal));
      return Math.round(randVal);
    }
    
    function odo_roll() {
      const odometerElements = document.querySelectorAll('.odometer');
      odometerElements.forEach((element) => {
        const targetValue = element.getAttribute('data-value');
        const odometer = new Odometer({
          el: element,
          value: 0,
          format: '(,ddd)',
          duration: 18000
        });
        odometer.update(rnd(10, 99));
        odometer.update(targetValue);
      });
    }
    
    //Odometer number rolling
    window.onload = setTimeout(odo_roll, 150);
    
    
    $(".odometer").hover(function() {
      odo_roll();
    });
    .odometer {
      font-size: 24px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/odometer.js/0.4.7/odometer.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/odometer.js/0.4.7/themes/odometer-theme-train-station.css">
    <section class="company-statistics">
      <div class="container">
        <div class="stats-wrapper">
          <div class="stats-content row">
            <div class="col-6 col-md-4 col-lg-4 stat-item">
              <div class="odometer" data-value="13">0</div>
            </div>
            <div class="col-6 col-md-4 col-lg-4 stat-item">
              <div class="odometer" data-value="10">0</div>
            </div>
            <div class="col-6 col-md-4 col-lg-4 stat-item">
              <div class="odometer" data-value="75">0</div>
            </div>
            <div class="col-6 col-md-4 col-lg-4 stat-item">
              <div class="odometer" data-value="18">0</div>
            </div>
            <div class="col-6 col-md-4 col-lg-4 stat-item">
              <div class="odometer" data-value="22">0</div>
            </div>
            <div class="col-6 col-md-4 col-lg-4 d-xl-none stat-item">
              <div class="odometer" data-value="45">0</div>
            </div>
          </div>
        </div>
      </div>
    </section>