Not sure if this is possible, but I'd like to transition between 4 words on my site. The words are pr0digies, 50 All-stars, 100% Max, and EV0LVED. In between those words, I'm trying to have the number 0 in pr0digies count up (0, 1, 2, 3, etc...) to 50 while the word pr0digies slowly fades and changes to 50 All-Stars... then again from 50-100 as the word changes to 100% Max... then lastly to the word EV0LVED.

I was thinking I could do this with photos through a gif or slideshow, or perhaps I could use a jquery animation of some sort... or maybe use divs somehow.

Anyways, let me know. Thanks a ton!

Dani AI

Generated

This thread landed on the right pattern: keep the changing text as real text (less work than sprites and much sharper on any device) and separate the three pieces around the changing digit. 's suggestion to split into pre/number/post is the simplest structure, and 's interval demo shows the basic idea. Below is a modern, practical refinement you can drop into the page that keeps timing accurate, reduces CPU use, and makes fades smooth without duplicating the earlier setInterval/count plugin code.

Use a tiny state table (pre/post/from/to/duration/hold) and drive the work with requestAnimationFrame plus timestamp-based interpolation. Update the DOM only when the rounded number actually changes, and toggle a CSS class to handle fade-in/out (use CSS opacity + transform for best performance). Put an ARIA live attribute on the numeric element so screen readers announce the changes.

// assumes elements with ids: pre, num, post
const states = [
  { pre: 'pr', post: 'digies', from: 0,  to: 50,  duration: 2000, hold: 600 },
  { pre: '',   post: ' All‑Stars', from: 50, to: 100, duration: 2000, hold: 600 },
  { pre: '',   post: '% Max',     from: 100,to: 100, duration: 1000, hold: 800 },
  { pre: 'EV', post: 'LVED',      from: 0,  to: 0,   duration: 800,  hold: 0   }
];

let idx = 0, start = null, last = null;
function frame(ts) {
  if (!start) start = ts;
  const s = states[idx];
  const t = ts - start;
  const progress = Math.min(1, t / Math.max(1, s.duration));
  const value = Math.round(s.from + (s.to - s.from) * progress);
  if (value !== last) { document.getElementById('num').textContent = value; last = value; }
  // handle end/hold and advance
  if (t >= s.duration + s.hold) {
    idx++;
    if (idx >= states.length) return; // stop, or set idx=0 to loop
    start = ts; last = null;
    document.getElementById('pre').textContent = states[idx].pre;
    document.getElementById('post').textContent = states[idx].post;
  }
  requestAnimationFrame(frame);
}
document.getElementById('pre').textContent = states[0].pre;
document.getElementById('post').textContent = states[0].post;
document.getElementById('num').textContent = states[0].from;
requestAnimationFrame(frame);

Practical notes: avoid extremely small intervals (1ms), prefer requestAnimationFrame; use CSS will-change: opacity, transform and transitions for fades; use position: fixed (bottom/right) if you want the element to stick to a corner; preload fonts; and add aria-live="polite" to the number span so screen readers aren’t flooded. If you need a logo-like look, SVG/text + CSS usually beats sprite sheets for responsiveness and retina support.

Recommended Answers

All 13 Replies

Member Avatar for Member #120589

An easy way to do it would be with three spans. One for prenumber, one for number itself, one for postnumber. Change pre and post when count up reaches a target number.

commented: great start! +2

Great advice, and an awesome start... but how do I add the change in surrounding words? The way that I'm envisioning it is that the words fade out and transition in slowly, as the counter is continuously moving with perfect timing at the 0, 50, and 100 intervals... then it all transitions to the final EVOLVE.

Here's where I'm currently at: (Thanks!)

<script type="text/javascript" src=""></script>



<style>

.timer{width:200px; margin:20px auto;text-align:center;display:block;font-size:20px}

</style>


<script>

(function($) {
    $.fn.countTo = function(options) {
        // merge the default plugin settings with the custom options
        options = $.extend({}, $.fn.countTo.defaults, options || {});

        // how many times to update the value, and how much to increment the value on each update
        var loops = Math.ceil(options.speed / options.refreshInterval),
            increment = (options.to - options.from) / loops;

        return $(this).each(function() {
            var _this = this,
                loopCount = 0,
                value = options.from,
                interval = setInterval(updateTimer, options.refreshInterval);

            function updateTimer() {
                value += increment;
                loopCount++;
                $(_this).html(value.toFixed(options.decimals));

                if (typeof(options.onUpdate) == 'function') {
                    options.onUpdate.call(_this, value);
                }

                if (loopCount >= loops) {
                    clearInterval(interval);
                    value = options.to;

                    if (typeof(options.onComplete) == 'function') {
                        options.onComplete.call(_this, value);
                    }
                }
            }
        });
    };

    $.fn.countTo.defaults = {
        from: 0,  // the number the element should start at
        to: 100,  // the number the element should end at
        speed: 1000,  // how long it should take to count between the target numbers
        refreshInterval: 100,  // how often the element should be updated
        decimals: 0,  // the number of decimal places to show
        onUpdate: null,  // callback method for every time the element is updated,
        onComplete: null,  // callback method for when the element finishes updating
    };
})(jQuery);

jQuery(function($) {
        $('.timer').countTo({
            from: 0,
            to: 100,
            speed: 2000,
            refreshInterval: 1,
            onComplete: function(value) {
                console.debug(this);
            }
        });
    });

</script>

<span class="timer"></span>

And here are my 4 images:

0 /// pr0digies:

50 /// 50 All-Stars:

100 /// 100% Max:

0 /// EVOLVED:

Can I create 100 different images and cycle through them, while somehow temporarily pausing at each of the 4 states? (Or more efficiently use one image and just adjust the coordinates... like this)

Maybe even put the image in the lower right corner so that it adjusts on scrolling? But again, I'm not too sure how I'd do that. I found this on the web:

onScrollHandler = function() {
  var newImageUrl = yourImageElement.src;
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  if (scrollTop > 100) {
     newImageUrl = "img1.jpg"
  }
  if (scrollTop > 200) {
     newImageUrl = "img2.jpg"
  }
  if (scrollTop > 300) {
     newImageUrl = "img3.jpg"
  }
  yourImageElement.src = newImageUrl;
};
object.addEventListener ("scroll", onScrollHandler);
Member Avatar for Member #120589

Why not just use text? I can't see the advantage of an image.

 var targets = [['pr','digies'],['',' All-stars'],['','% Max'],['EV','LVED']];
 var limits = [0,50,100];

Cycle thru:

<span class="prenumber"></span><span class="number"></span><span class="postnumber"></span>

Just increment number and check on each iteration for limit, with inArray you can flick to the next array item in targets. Should be simple.

How would I apply those vars?

And I thought the images would better serve my limited knowledge. I found a couple of sites (here's one) that show how to cycle through css sprites for a slideshow. Maybe I can speed up the slideshow after creating all the points in one files. I could even slow it down by repeating the target points as needed.

Here's where I'm at on your code. No idea how to add the words around it. Thank you for all the help, btw.

<script type="text/javascript" src=""></script>
<style>
.number{width:200px; margin:20px auto;text-align:center;display:block;font-size:20px}
</style>
<script>
(function($) {
    $.fn.countTo = function(options) {
        // merge the default plugin settings with the custom options
        options = $.extend({}, $.fn.countTo.defaults, options || {});
        // how many times to update the value, and how much to increment the value on each update
        var loops = Math.ceil(options.speed / options.refreshInterval),
            increment = (options.to - options.from) / loops;
        return $(this).each(function() {
            var _this = this,
                loopCount = 0,
                value = options.from,
                interval = setInterval(updatenumber, options.refreshInterval);
            function updatenumber() {
                value += increment;
                loopCount++;
                $(_this).html(value.toFixed(options.decimals));
                if (typeof(options.onUpdate) == 'function') {
                    options.onUpdate.call(_this, value);
                }
                if (loopCount >= loops) {
                    clearInterval(interval);
                    value = options.to;
                    if (typeof(options.onComplete) == 'function') {
                        options.onComplete.call(_this, value);
                    }
                }
            }
        });
    };
    $.fn.countTo.defaults = {
        from: 0,  // the number the element should start at
        to: 100,  // the number the element should end at
        speed: 1000,  // how long it should take to count between the target numbers
        refreshInterval: 100,  // how often the element should be updated
        decimals: 0,  // the number of decimal places to show
        onUpdate: null,  // callback method for every time the element is updated,
        onComplete: null,  // callback method for when the element finishes updating
    };
})(jQuery);
jQuery(function($) {
        $('.number').countTo({
            from: 0,
            to: 100,
            speed: 2000,
            refreshInterval: 1,
            onComplete: function(value) {
                console.debug(this);
            }
        });
    });

var targets = [['pr','digies'],['',' All-stars'],['','% Max'],['EV','LVED']];
 var limits = [0,50,100];


</script>
<span class="prenumber"></span><span class="number"></span><span class="postnumber"></span>

And here's what I have so far on my sprite idea. I'm struggling with the fade in/out effect, as I'd like for it to not fade at all but just appear as if the number is changing. This might be a non-issue once I create and align the sprite properly.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css" >
#slideContainer {
        width: 100px;
        height: 100px;
        overflow: hidden;
        border: 0px;
        margin: 20px auto;
        position: relative;
    }
    #slideWrap {
        height: 100px;
        position: absolute;
        top: 0;
        left: 0;
    }
    .slide {
        width: 100px;
        height: 100px;
        float: left;
        background: url() no-repeat 0 0;
    }

    .two {
        background: url() no-repeat -100px 0;
    }

    .three {
        background: url() no-repeat -200px 0;
    }

    .four {
        background: url() no-repeat -300px 0;
    }</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>

// JavaScript Document
$(document).ready(function() {
    var slides = $('.slide');
    var numberSlides = slides.length;
    var slideWidth = $('.slide').width();
    var wrap = $('#slideWrap')

    wrap.width(numberSlides * slideWidth);

    function moveMent() {
        for(r=0; r<100; r++) {
            for(i=0; i<numberSlides-1; i++) {
                wrap
                    .delay(500)
                    .fadeTo(50, 0)
                    .animate({               
                        left : '-=100px'
                    })
                    .fadeTo(50, 1)  
            }
            wrap.delay(3000).fadeTo(500, 0).animate({left : '0'}).fadeTo(500, 1);
        }
    };

    moveMent(); 

});

</script>
</head>

<body>
<div id="slideContainer">
    <div id="slideWrap">
        <div class="slide one"></div>
        <div class="slide two"></div>
        <div class="slide three"></div>
        <div class="slide four"></div>
    </div>
</div>
</body>
</html>

I tried to do using a pure jquery and here is the code:

<h1 id="text">pr0digies</h1>
<script>
    var count = 0;
    var interval = null;
    $(document).ready(function () {
        interval = setInterval(updateContent, 200);
    });

    function updateContent(){
        count++;
        console.log(count+" second passed");
        if(count < 50){
            $( "#text" ).html("pr"+count+"digies");
        }else if(count < 100){
            $( "#text" ).html(count+" All-stars");
        }else if(count == 100){
            $( "#text" ).html(count+"% Max");
        }else if(count > 100){
            $( "#text" ).html("EV0LVED");
            clearInterval(interval);
        }
    }
</script>
commented: That totally worked. Thanks a ton. I'll work on making it a bit more dramatic :-) +2
Member Avatar for Member #120589

Here's my take on it:

http://jsfiddle.net/diafol666/tzqmz8Lp/

I didn't get the timing quite right on the last two I don't think, but hope it's enough to give you the gist. Also add a fade from one item to the next for a smoother transition. Anyway, just a bit of fun.

commented: That's exactly where I wanted to go! Awesome. Thank you!!! +0

You mentioned a fade property. I've aligned the words and also paused the animiation to emphasize the stages, but a fade out after each stage and a fade-into the last one would be perfect.

Either way, you knocked it out the park. Forever grateful.

 var targets = [
          ['pr','digies',1,0,0,2000],
          ['pr','digies',50,0,1,100],
          ['&nbsp&nbsp',' All-stars',1,50,0,2000],
          ['&nbsp&nbsp',' All-stars',50,50,1,100],
          ['&nbsp&nbsp','% Max',1,100,0,2000],
          ['&nbspEV','LVED',1,0,0,15000]
      ];
Member Avatar for Member #120589

Forgot to mention, the Array has this structure:

 //Array Structure
  //prenumber content, postnumber content, no. of iterations, start display number, increment by, intervalTime in ms
  var targets = [
      ['pr','digies',50,0,1,100],
      ['',' All-stars',50,50,1,100],
      ['','% Max',1,100,0,2000],
      ['EV','LVED',1,0,0,5000]
  ];

But I think you worked it out anyway

commented: Yep, figured that out. Still trying to see if I can add fade-in/out effects. Thx a ton! +2

So I've made it look pretty. Just one more thing. I'd like to add one more string of words hanging on the end of every paused step. I tried and thought I was following your process, but it all went horribly wrong. I'll post where I'm at now, and then I'll repost where I was trying to get at. Thanks again. Sorry if I'm being a headache.

  <script type='text/javascript' src='http://code.jquery.com/jquery-1.11.0.js'></script>

    <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Orbitron" />




  <style type='text/css'>
            .anim{
            font-weight: bold;
        font-family: 'Orbitron', sans-serif;
        font-size: 48px;
        }
        .number{
            color:red;

        }
        .prenumber, .postnumber{
            color: black;
        }

  </style>



<script type='text/javascript'>//<![CDATA[ 
$(window).load(function(){
 var targets = [
           ['pr','digies',1,0,0,2000],
          ['pr','digies',50,0,1,100],
          ['&nbsp&nbsp&nbsp',' All-Stars',1,50,0,2000],
          ['&nbsp&nbsp&nbsp',' All-Stars',50,50,1,100],
          ['&nbsp&nbsp&nbsp','% Max',1,100,0,2000],
          ['&nbsp&nbspEV','LVED',1,0,0,2000],
          ['&nbsp&nbspEV','LVED',1,0,0,15000]
      ];

      var interval;
      var item;  //current targets array item in use
      var counter; //normal counter
      var increment; //increment by
      var limit; //counter limit - once counter hits this - go to next
      var intervalID;

      var cycle = true; //loop "animation" false = stay on last targets item ad stop animation


      function init()
      {
          $('.anim').html('<span class="prenumber"></span><span class="number"></span><span class="postnumber"></span>');
          item = 0;
          next(item);
      }

      function next()
      {
          if(item == targets.length)
          {
              if(cycle == true)
              {
                  item = 0;
              }else{
                  stopTime();
                  return;
              }
          }

          $('.anim .prenumber').html(targets[item][0]);
          $('.anim .postnumber').html(targets[item][1]);
          $('.anim .number').html(targets[item][3]);
          increment = targets[item][4];
          interval = targets[item][5];
          limit = targets[item][2];
          counter = 0;
          if(intervalID) stopTime();
          intervalID = window.setInterval(countUp, interval);
          console.log('NEXT interval ' + interval);
      }

      function countUp()
      {
          counter++;
          var current = parseInt($('.anim .number').html()) + increment;
          $('.anim .number').html(current);

          if(counter > limit)
          {
              item++;
              next();
          }

      }

      function stopTime()
      {
          clearInterval(intervalID);
      }


      init();
});//]]>  

</script>


  <div class="anim"></div>

And here's my attempt. It soemtimes works; sometimes doesn't. If you find any errors, let me know.

  <script type='text/javascript' src='http://code.jquery.com/jquery-1.11.0.js'></script>

    <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Orbitron" />




  <style type='text/css'>
            .anim{
            font-weight: bold;
        font-family: 'Orbitron', sans-serif;
        font-size: 48px;
        }
        .number{
            color:red;

        }
        .prenumber, .postnumber{
            color: black;
        }
        .affixation{
            color: #cccccc;
            font-size:28px;
        }

  </style>



<script type='text/javascript'>//<![CDATA[ 
$(window).load(function(){
 var targets = [
           ['pr','digies','&nbspdaycare',1,0,0,2000],
          ['pr','digies','&nbsp',50,0,1,100],
          ['&nbsp&nbsp&nbsp',' All-Stars','&nbspbasketball',1,50,0,2000],
          ['&nbsp&nbsp&nbsp',' All-Stars','&nbsp',50,50,1,100],
          ['&nbsp&nbsp&nbsp','% Max','fitness',1,100,0,2000],
          ['&nbsp&nbspEV','LVED','&nbsp',1,0,0,2000],
          ['&nbsp&nbspEV','LVED','&nbsp.center',1,0,0,15000]
      ];

      var interval;
      var item;  //current targets array item in use
      var counter; //normal counter
      var increment; //increment by
      var limit; //counter limit - once counter hits this - go to next
      var intervalID;

      var cycle = true; //loop "animation" false = stay on last targets item ad stop animation


      function init()
      {
          $('.anim').html('<span class="prenumber"></span><span class="number"></span><span class="postnumber"></span><span class="affixation"></span>');
          item = 0;
          next(item);
      }

      function next()
      {
          if(item == targets.length)
          {
              if(cycle == true)
              {
                  item = 0;
              }else{
                  stopTime();
                  return;
              }
          }

          $('.anim .prenumber').html(targets[item][0]);
          $('.anim .postnumber').html(targets[item][1]);
          $('.anim .affixation').html(targets[item][2]);
          $('.anim .number').html(targets[item][4]);
          increment = targets[item][5];
          interval = targets[item][6];
          limit = targets[item][3];
          counter = 0;
          if(intervalID) stopTime();
          intervalID = window.setInterval(countUp, interval);
          console.log('NEXT interval ' + interval);
      }

      function countUp()
      {
          counter++;
          var current = parseInt($('.anim .number').html()) + increment;
          $('.anim .number').html(current);

          if(counter > limit)
          {
              item++;
              next();
          }

      }

      function stopTime()
      {
          clearInterval(intervalID);
      }


      init();
});//]]>  

</script>


  <div class="anim"></div>

Check all that. I got it working. See http://www.evolved.center/

Thanks, everyone!

commented: Good work +15
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.