Add JavaScript Animated Progress Bars in Six Steps

stages of the moon

Besides allowing users to interact with the screen (e.g., clicking a button), JavaScript can add personality and style to your page. For example, I added animated progress circles to my website to highlight my technical and writing skills in a unique way.

skill progress circles
There are lots of reasons and ways to use progress bars and circles, but it requires using JavaScript as well as HTML and CSS, which can complicate things for someone new at developing websites or using JavaScript. The following six steps make it easy for you to create, style, and animate progress bars or circles—all while maintaining a great download speed.

Step 1: Creating Progress Bars

In this tutorial, I’ll be using the ProgressBar.js library to create my progress circles because the documentation was easy to use and the code was relatively simple to customize. I also did not notice any changes in loading time when using these progress circles, and I found them aesthetically pleasing. Using this library, I’m going to show you how to incorporate these progress circles into your website and personalize them to fit your project.

Let’s start with a working example from the ProgressBar.js documentation:

progress bar initial code
In this documentation, you can see the three main parts necessary to insert your progress circles: an HTML component that physically inserts the circle into the website, a CSS component that modifies the appearance, and a JavaScript component that creates and defines each instance of the progress circle.

HTML component

Displaying the progress circle is simple and only requires one line of code. Progress bars must be housed within <div> tags, which is included in the HTML file.

<div id="container">

With this one line of code, you call the variable ID that you created (container) and it will display on your website. Please remember that your variable name needs to be consistent across the HTML, CSS, and JavaScript files. It doesn’t matter what you call it as long as it makes sense to you and you are consistent throughout the files.

CSS component

Using CSS, you can alter the appearance and style of your progress circle. You can either create an external CSS file or add it internally within the tag in your HTML document. Style the element with the #ID selector.

#container { 
    margin: 20px; 
    width: 200px;
    height: 200px; 
}

In this example, #container is the #ID selector. (Again, this variable should match the one used in your JavaScript and HTML files.) The margin property creates space around the progress circle, and the width and height properties determine the size of the circle. You can adjust these properties and add more to create the progress circle you want.

JavaScript component

Using JavaScript, you create and animate the progress circle.

var bar = new ProgressBar.Circle(container, {
    color: ‘#FFEA82',
    trailColor: '#eee',
    trailWidth: 1,
    duration: 1400,
    easing: 'bounce',
    strokeWidth: 6,
    from: {color: '#FFEA82', a:0},
    to: {color: '#ED6A5A', a:1},
    // Set default step function for all animate calls
    step: function(state, circle) {
      circle.path.setAttribute('stroke', state.color);
    }
});
bar.animate(1.0); // Number from 0.0 to 1.0

In the first line of code, you declare the variable (called “bar”) and define it as a new ProgressBar.Circle, which is a function that is part of the ProgressBar.js library. Then you include the ID selection name and pass the properties for the circle. (You will need to create additional variable names if you use more than one circle.)

Using the hex color codes, select a color for the circle. The tags trailColor and trailWidth determine the color and size of the initial line that marks where the animated line will be. Duration refers to how quickly the outer band of the circle fills in: Decreasing the number causes the band to fill in quickly, and increasing the number slows down the process. Easing controls the style of how the line will be filled in; in this case, the outer band bounces as it finishes filling in. You can also control the width of the stroke with strokeWidth.

For the color of the circle, you have two options: You can use a solid color or transition from one color to another. (This example includes code for both options, but you can just include the appropriate lines needed.) The color defined by the line “color: ‘#FFEA82'” sets up a single color for your progress circle. However, if you want to transition from one color to another, then include the following lines of code.

from: {color: '#FFEA82', a:0},
to: {color: '#ED6A5A', a:1},
step: function(state, circle) {
  circle.path.setAttribute('stroke', state.color);
}

The first two lines of code control the beginning and ending colors. The next lines of code set the default step function for all the animate calls. The “step:function(state,circle)” gets called at each step in the animation automatically by ProgressBar.js and the “circle.path.setAttribute” makes sure that the bar has the correct color at each step of the animation.

Finally, you have to call the function (bar.animate) and select how much the line will progress on the circle using a number from 0.0 to 1.0, with 1.0 being 100% filled in.

Step 2: Modifying Progress Bars

Modifying using JavaScript

Using this initial code, I modified the circles to make them the color and style I wanted. I also personalized the ID name and changed it from #container to #progressbar_skills.

var bar = new ProgressBar.Circle(progressbar_skills, {
  color: '#f1d204',
  trailColor: '#eee',
  trailWidth: 1,
  duration: 1400,
  easing: 'bounce',
  strokeWidth: 6,
  from: {color: '#515050', a:0},
  to: {color: '#f1d204', a:1},
  // Set default step function for all animate calls
  step: function(state, circle) {
    circle.path.setAttribute('stroke', state.color);
  }
});
bar.animate(1.0);  // Number from 0.0 to 1.0

You can also change the stroke size of the progress circle by adding width to your JavaScript code. To do this, add a width parameter within the from/to structures and add the setAttribute function: circle.path.setAttribute('stroke-width', state.width);.

from: {color: '#515050', a:0, width: 1},
to: {color: '#f1d204', a:1, width: 4},
// Set default step function for all animate calls
step: function(state, circle) {
  circle.path.setAttribute('stroke', state.color);
  circle.path.setAttribute('stroke-width', state.width);

Modifying using CSS

You can also use CSS to style the circles. Here is a sample CSS for the ID selection “techSkill1”:

#techSkill1 {
margin: 5px;
	width: 140%;
	height: 140%;
	text-transform: uppercase;
	color: #444;
	font-family: 'Raleway', sans-serif;
	font-size: 18px;
	font-weight: bold;
	}

Step 3: Adding Text Inside the Progress Circle

After you have customized the progress circle, you may want to add text inside. Unfortunately, you cannot just write text in-between the <div> tag for the progress circle. Instead, insert the following code to your JavaScript file:

circle.setText("HTML");
  }
});
bar.text.style.fontFamily = '"Raleway", Helvetica, sans-serif';
bar.text.style.fontSize = '2rem';

Of course, you can easily change the style to fit your needs. To change the font color, add the following.

bar.text.style.color = 'black';

Then, select the color you want. You can also style the text using CSS instead of JavaScript.

Step 4: Putting the Animated Circles on a Web Page

First, reference the JavaScript file(s).

If you are using an external JavaScript file, then you need to add that link to your <script></script> tag in your HTML document:

<script type="text/javascript" src="js/progresscircle.js"></script>

You will also need to include the ProgressBar.js library:

<script type="text/javascript" src="https://cdn.rawgit.com/kimmobrunfeldt/progressbar.js/0.5.6/dist/progressbar.js"></script>

Then, remember to draw the circles when loading the window or when scrolling.

Your JavaScript file is not finished because right now the code does not instruct the computer when to draw these circles. You can easily fix this problem by enclosing your JavaScript code for drawing your circles inside the following function.

window.onload = function onLoad() { }

This code instructs the computer to draw and animate the circles as soon as the window is loaded. Of course, depending on your layout, this may present a problem if you want do not want to animate the circles until the user has reached the appropriate section.

Step 5: Creating Multiple Progress Circles

Create variable and ID names for each progress circle

If you want to create multiple progress circles, you need to create new variable and ID names for each progress circle. For example, in the following line of code, the variable is “barS1” and the ID is “#techSkill1.”

barS1 = new ProgressBar.Circle('#techSkill1', { });

You call the JavaScript function in your HTML using the following line of code.

<div id="techSkill1"></div>

multiple progress circles

Adjust the layout using Bootstrap grid system

But what if you want your progress circles horizontal? The Bootstrap grid system makes adjusting the row layout simple. The grid system is based on a 12-column layout, and it allows you to define how many columns you want in a row—with the total number adding up to 12. The following code will make the object span the width of the page.

<div class="row">
    <div class="col-xs-12 col-md-12">
        content you want to display
    </div>
</div>

But if you want three columns in a row on the page, then use the following code.

<div class="row">
    <div class="col-md-4">
        content you want to display
    </div>
    <div class="col-md-4">
        content you want to display
    </div>
    <div class="col-md-4">
        content you want to display
    </div>
</div>

And if you want a second row of circles, just create a new <div class="row"></div> and make some more. To add space between the circles, you can insert columns with nothing included in the “content you want to display” part, so they will show up as blank space. In the following code, the first <div class="col-md-4"></div> is empty, and the other two columns contain the content.

<div class="row">
    <div class="col-md-4">
    </div>
    <div class="col-md-4">
        content you want to display
    </div>
    <div class="col-md-4">
        content you want to display
    </div>
</div>

Step 6: Animate Progress Circles When User Scrolls

After spending all this time perfecting your animation of the progress circles, you do not want it to load and animate before the user makes it to that section of your website. You want to show off all that hard work. One way to accomplish this is to use the jQuery scroll function. The following code uses jQuery’s window.pageYOffset property, which returns the user’s position in the page (i.e., the number of pixels from the top of the page).

$(window).scroll(function() {
  var y_scroll_pos = window.pageYOffset;
  var scroll_pos_test = 1400;
	// set to whatever you want it to be
    if(y_scroll_pos > scroll_pos_test) {
    bar.animate(1.0);
});

This example uses a simple conditional statement that checks the scroll position of the user. In this case, the circles animate when the user scrolls at least 1400 pixels from the top. To do this, create a variable (e.g., scroll_pos_test) and set it to the appropriate value. (To find the appropriate value, you will need to find the target position for your project so play around and adjust that number as needed.)

Boolean expressions to avoid an infinite loop

This code, however, is still incomplete because you run the risk of breaking the browser by creating an infinite loop. The computer waits for the user’s mouse to hit the target Y position of 1400, and then it continues to draw circles so nothing else can load.

To fix the infinite loop, you need to create a Boolean expression. In JavaScript, a Boolean returns a value of either true or false, so you use the Boolean () function to find out if an expression or variable is true or false. When you use this type of expression, the computer will know to run the code for the progress circles once and then stop.

To create a Boolean expression, you first declare a new variable (e.g., var bSkills=0) and then you write IF statements to make a true/false scenario.

var bSkills=0;
$(window).scroll(function() {
  var y_scroll_pos = window.pageYOffset;
  var scroll_pos_test = 1400;
	// set to whatever you want it to be
    if(y_scroll_pos > scroll_pos_test) {
      if (bSkills == 0) {
        bSkills = 1;
         barS1.animate(1.0);
//bar animate code
});

With this code, you initialize the variable to false (var bSkills=0) and then tell the computer to animate the progress circles if both the variable is equal to 0 and the user’s mouse is at the target Y position. The second Boolean expression within this code (bSkills=1) sets the variable to 1, not 0, so when the computer reads the code again, it finds that the Boolean expression is now false (the variable is not 0 but 1), so it should not make any more animated progress circles. In other words, this Boolean variable ensures that the progress circle is animated only once as soon as the user reaches the intended position. Once the bar has been animated (and bSkills is set to 1), the browser will not try to re-animate the circle even though the user has passed the target Y position. Without this Boolean, the browser will try to start the animation infinitely once the user passes the target Y position.

Improving the speed of your website

The Boolean expressions fix the infinite loop problem, but now the progress circles only load when the user reaches that set Y position. This means that once the user scrolls down to your target Y position, they will have to wait for the computer to create, draw, and then animate the circles, which slows down the speed of the site and may cause the user to get frustrated or miss the amazing circles you have spent so much time creating.

One way to avoid this problem is to create and load the progress circles when the website loads, but not animate them until the user reaches that section of the web page. To do this, use the window.onload=function onLoad () to first draw the circles when the user loads the page, and then create a Boolean using the $(window).scroll(function() {}) to animate the circles when the user’s mouse gets to a set Y position.

//load progress circles when window opens
var barS1;
  window.onload = function onLoad() {
    barS1 = new ProgressBar.Circle('#techSkill1', {
    trailColor: '#eee',
    trailWidth: 1,
    duration: 5000,
    easing: 'bounce',
    strokeWidth: 6,
    from: {color: '#545454', a:0, width: 1},
    to: {color: '#880822', a:1, width: 6},
    // Set default step function for all animate calls
    step: function(state, circle) {
      circle.path.setAttribute('stroke', state.color);
      circle.path.setAttribute('stroke-width', state.width);
      circle.setText("HTML");
    }
    });
  }
//Boolean to active circle animation
var animateCircles=0;
  $(window).scroll(function() {
    var y_scroll_pos = window.pageYOffset;
    var scroll_pos_test = 1300;
  	// set to whatever you want it to be
      if(y_scroll_pos > scroll_pos_test) {
        if (animateCircles == 0) {
          animateCircles = 1;
          barS1.animate(1.0); // Number from 0.0 to 1.0
        }
      }});

If you want to have multiple progress circles, you must have only one window.onload function (or the computer gets confused with the multiple onload commands), so place all the variables before the onload function and then put all the code to draw the circles inside the brackets for the window.onload function.

var barS1;
var barS2;
window.onload = function onLoad() {

    barS1 = new ProgressBar.Circle('#techSkill1', {
    trailColor: '#eee',
    trailWidth: 1,
    duration: 5000,
    easing: 'bounce',
    strokeWidth: 6,
    from: {color: '#545454', a:0, width: 1},
    to: {color: '#880822', a:1, width: 6},
    // Set default step function for all animate calls
    step: function(state, circle) {
      circle.path.setAttribute('stroke', state.color);
      circle.path.setAttribute('stroke-width', state.width);
      circle.setText("HTML");
    }
    });

    barS2 = new ProgressBar.Circle('#techSkill2', {
      trailColor: '#eee',
      trailWidth: 1,
      duration: 5000,
      easing: 'bounce',
      strokeWidth: 6,
      from: {color: '#545454', a:0, width: 1},
      to: {color: '#880822', a:1, width: 6},
      // Set default step function for all animate calls
      step: function(state, circle) {
        circle.path.setAttribute('stroke', state.color);
        circle.path.setAttribute('stroke-width', state.width);
        circle.setText("CSS");
      }
    });

  }

Follow this same pattern to animate the progress circles. Define var animateCircles once and then list all the progress circles animations at the end—wrapped inside the $(window).scroll function.

//Boolean to active circle animation
var animateCircles=0;
  $(window).scroll(function() {
    var y_scroll_pos = window.pageYOffset;
    var scroll_pos_test = 1200;
  	// set to whatever you want it to be
      if(y_scroll_pos > scroll_pos_test) {
        if (animateCircles == 0) {
          animateCircles = 1;
          barS1.animate(1.0); // Number from 0.0 to 1.0
          barS2.animate(0.9);
          barS3.animate(0.7);
          barS4.animate(1.0);
          barS5.animate(1.0);
          barS6.animate(1.0);
          barS7.animate(0.6);
          barS8.animate(0.5);
          barS9.animate(1.0);
          barS10.animate(1.0);
        }
      }});

You can now easily create, style, and animate progress circles or bars for your project. Be creative and happy coding!

Leave a Reply