JavaScript: Creating a spinner that spins when hovered on

In this post, we are going to create a spinner for our browser. We will be using HTML and CSS for the styling, and JavaScript to handle the animation and behaviour.

Our requirements

Let us list down the requirements of our spinner:

  1. Our spinner must be circular in shape.
  2. It must have four colors.
  3. We must be able to adjust its speed.
  4. Our spinner must spin only when we move our mouse over it.
  5. When we withdraw our mouse, our spinner must stop.

Let us get started.

The CSS

We are going to start with the CSS of our spinner. Create a new HTML file. Type in the following CSS into the style tag:

.spinner
{
  width: 0px;
  height: 0px;
  border: 50px solid;
  border-radius: 50%;
  border-top-color: red;
  border-left-color: blue;
  border-bottom-color: orange;
  border-right-color: green;
}

The HTML

Our spinner is a single empty ‘div’ element. Let us create it. Add the following code in the body tag of the file:

<div class="spinner" id="spinner"></div>

We give our div a class to apply the styles of the spinner on it. We also give it an id so that we can get the element using Javascript. Our current spinner should look something like this:

The JavaScript: Setting up the rotation

We will now use Javascript to get the behavior we desire. Let us do this step by step.

Type the following code into the script tag of the file. Note that the script tag should come after the body tag.

const spinner=document.getElementById('spinner');
let angle=0;

We get our spinner and store it in the variable of the same name. We also create a variable called ‘angle’. ‘angle’ will contain the degrees by which our spinner has rotated.

Now we code a function to actually rotate our spinner. Add the following code to the script tag:

const rotate=function(element,step,delay)
{
  const _rotate=function()
  {
    angle+=step;
    angle%=360;
    element.style.transform=`rotate(${angle}deg)`;
  };
  const intval=window.setInterval(_rotate,delay);
  return intval;
};

Let us understand this.

We create a function ‘rotate’ which takes three arguments:

  1. The element to rotate. In this case, our spinner.
  2. The number of degrees to rotate each time.
  3. The time interval after which the spinner must rotate again.

Inside this function, we define another function ‘_rotate’. This function actually performs the rotation for us in three steps:

  1. Update the value of ‘angle’ using the step argument specified.
  2. Wrap the ‘angle’ around 360 degrees. We do this because 360 degrees signifies one complete rotation and we do not want our angle to increase without bounds.
  3. Transform the spinner by rotating it by the calculated number of degrees.

We repeatedly call this ‘_rotate’ function using ‘window.setInterval’. The ‘window.setInterval’ function takes two arguments:

  1. The function to execute again and again.
  2. The time delay in milliseconds after each execution.

Our ‘rotate’ function returns the id of the interval for us to store it separately. We will see why later.

To verify that this code works, call ‘rotate’ with an arbitrary step and time delay.

rotate(spinner,5,50);

You should see your spinner spin in the browser.

The JavaScript: Controlling our spinner

We have managed to get our spinner to work. Now we need to create the ‘hover’ behaviour.

Add the following code to our script tag:

spinner.addEventListener('mouseenter',function(event)
{
  const rot=rotate(spinner,5,50);
  spinner.addEventListener('mouseleave',function(event)
  {
    window.clearInterval(rot);
  },
  {
    once:true,
  });
});

Several things are going on here. Let us examine them one by one.

We begin by attaching an event listening function to our spinner. This function will be fired whenever our mouse enters the region of our spinner. When it fires, the rotation of the spinner is started with the given step and time delay. The interval id of the rotation is stored separately.
Along with this, another event listener is also attached to our spinner, this time to fire when our mouse leaves the region of the spinner. When our mouse leaves the spinner, the ‘window.clearInterval’ function to stop the rotation using its interval id.

There is one important difference to note between the two event listeners:

When we register the event listener for the ‘mouseleave’ event, we pass in an additional object. That object contains a single property ‘once’ which is set to ‘true’. What this means is that our mouseleave event listener will fire only once. Once it has been fired, it will be detached from our spinner and will not be able to fire again.

The reason we do this is profound.

Assume that we had not specified the additional object parameter while registering the ‘mouseleave’ event handler. Every time we entered the region of the spinner, a new ‘mouseleave’ event handler would be attached. We would have several handlers each doing the same thing.
By specifying the third object parameter, we ensure that our ‘mouseleave’ event handler is removed once it has been fired. This ensures that there are no more event handlers when the ‘mouseenter’ event handler is triggered again. Our ‘mouseenter’ event handler can safely attach another event handler for the ‘mouseleave’ event.

The complete spinner code

Putting everything together, we finally have our spinner ready!

<html>
  <head>
    <style>
      .spinner
      {
        width: 0px;
        height: 0px;
        border: 50px solid;
        border-radius: 50%;
        border-top-color: red;
        border-left-color: blue;
        border-bottom-color: orange;
        border-right-color: green;
      }
    </style>
  </head>
  <body>
    <div class="spinner" id="spinner"></div>
    <script>
      const spinner=document.getElementById('spinner');
      let angle=0;
      const rotate=function(element,step,delay)
      {
        const _rotate=function()
        {
          angle+=step;
          angle%=360;
          element.style.transform=`rotate(${angle}deg)`;
        };
        const intval=window.setInterval(_rotate,delay);
        return intval;
      };
      spinner.addEventListener('mouseenter',function(event)
      {
        const rot=rotate(spinner,5,50);
        spinner.addEventListener('mouseleave',function(event)
        {
          window.clearInterval(rot);
        },
        {
          once:true,
        });
      });
    </script>
  </body>
</html>

Customizing the spinner

We have reached the end of our discussion of creating a spinner. In wrapping up, I would like to mention a few methods by which you could customize your spinner further.

  • Changing the colors:

The colors can be changed by modifying each ‘border-*-color’ attribute in the CSS.

  • Modifying the speed:

You can get the speed of your choice by adjusting the step and delay arguments of the ‘rotate’ function.

  • Modifying the spinner size:

You must change the border thickness in the ‘border’ CSS property.

Leave a Reply

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