Detailed explanation of JavaScript animation function encapsulation

Detailed explanation of JavaScript animation function encapsulation

1. Principle of animation function

Core principle: Continuously move the box position through the timer setInterval().

Implementation steps:

  1. Get the current position of the box
  2. Let the box add 1 moving distance to its current position
  3. Use a timer to repeat this operation
  4. Add a condition to end the timer
  5. Note that this element needs to be positioned before element.style.left can be used

As shown below:

Given a box, let it slowly move to the position of 300px.

The code is as follows:

<style>
   div{
        position: absolute;
        left: 0;
        top: 0;
        width: 100px;
        height: 100px;
        background-color: cyan;
    }
</style>
</head>
<body>
    <div></div>
    <script>
        var div = document.querySelector('div');
        var timer = setInterval(function(){
            if(div.offsetLeft >= 300){
                clearInterval(timer);
            }
            div.style.left = div.offsetLeft + 1 + 'px';
        },30); 
    </script>
</body>

The running results are:

Run successfully.

But what if several elements need to be animated at the same time? We can consider encapsulating it into a simple animation function.

2. Simple encapsulation of animation functions

The function needs to pass 2 parameters, the animation object and the distance to move to. As shown below:

 function animate(obj,target){
            var timer = setInterval(function(){
            if(obj.offsetLeft >= target){
                clearInterval(timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';
        },30);
        }

We can achieve the animation effect by calling the above encapsulated function. For example, given two different boxes, call the animation function separately:

 <style>
       .box1{
            position: absolute;
            left: 0;
            top: 50px;
            width: 100px;
            height: 100px;
            background-color: cyan;
        }
        .box2{
            position: absolute;
            left: 0;
            top: 155px;
            width: 150px;
            height: 150px;
            background-color:deepskyblue;
        }
    </style>

<body>
   <div class="box1"></div>
   <div class="box2"></div>
    <script>
        function animate(obj,target){
            var timer = setInterval(function(){
            if(obj.offsetLeft >= target){
                clearInterval(timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';
        },30);
        }
        var box1 = document.querySelector('.box1');
        var box2 = document.querySelector('.box2');
        animate(box1,300);
        animate(box2,400);
    </script>
</body>

The effect is:

The animation effect was successfully achieved.

However, the animation function encapsulated above still has problems. Every time we call an animation function, a piece of memory space will be opened up for us, which will cause the problem of wasting memory resources. Moreover, the animation function we call each time is named with the same name, which can easily cause ambiguity. Therefore, we can use different timers for different elements (use our own timer).

3. Animation functions record different timers for different elements

Core principle: JS is a dynamic language that can easily add attributes to the current object.

By adding attributes to objects to add timers to different elements, we can encapsulate it as follows:

function animate(obj,target){
  obj.timer = setInterval(function(){
     if(obj.offsetLeft >= target){
         clearInterval(obj.timer);
     }
     obj.style.left = obj.offsetLeft + 1 + 'px';
 },30);
}

Of course, if we want an element to be animated only after we perform a series of operations, we can add a specific event to it and write the function call in the event.

Take the first example as an example, add a click event to it, and the box will move only when the button is clicked:

 var box1 = document.querySelector('.box1');
        var btn = document.querySelector('button')
       btn.addEventListener('click',function(){
            animate(box1,300);
        })

The effect is:

The effect is achieved, but what will happen if we keep clicking the button?

We will find that as we continue to click the button, the box will run faster and faster. This is because we have started too many timers at the same time. How to solve it? The solution is to let our element clear the previous timer first and keep only one timer to execute, so we can add an operation to clear the timer at the top of the function. The code is:

  function animate(obj,target){
            clearInterval(obj.timer);
            obj.timer = setInterval(function(){
            if(obj.offsetLeft >= target){
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';
        },30);
        }
        var box1 = document.querySelector('.box1');
        var btn = document.querySelector('button');
       btn.addEventListener('click',function(){
            animate(box1,300);
        })

The operating effect at this time is

Successfully achieved.

Through the above series of operations, we can find that the animations we have implemented are all at a uniform speed. In order to make the effect more beautiful, we can make our animation run at a slow speed.

4. Principle of easing effect

Easing animation is to change the speed of element movement, the most common is to slowly stop the speed.

  • Idea: Let the distance the box moves each time gradually decrease, and the speed will slowly drop.
  • Core algorithm: (target value - current position) / 10 as the distance step for each move
  • Stop condition: Stop the timer when the current box position is equal to the target position

Note that the step value needs to be rounded

Taking the above example, when we click the button, we want the element to move at a slow speed. We can change the encapsulated animation function to:

function animate(obj,target){
            clearInterval(obj.timer)
            obj.timer = setInterval(function(){
                var step = (target - obj.offsetLeft)/10;
            if(obj.offsetLeft == target){
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + step + 'px';
        },30);
        }

The effect is:

Doesn’t this effect look better? But let's check how far our element has moved. Is it exactly at the target value of 300px?

By checking, we found that our elements did not reach the specified position. This is because our step formula is problematic. When performing division operations, there may be decimals, which will lead to position deviations. Therefore, we need to round the step formula. Since the elements are moving forward (positive direction), the strategy we adopt is to round up:

 var step = Math.ceil((target - obj.offsetLeft)/10);

Now let's take a look at the final destination:

At this time, we have just reached the target location.

5. Animation function moves between multiple target values

But what if our step size is negative?

For example, now there is a box, add two buttons to it, one moves the element to 400px, and the other moves the element to 700px:

function animate(obj,target){
    clearInterval(obj.timer)
     obj.timer = setInterval(function(){
         var step = Math.ceil((target - obj.offsetLeft)/10);
     if(obj.offsetLeft >= target){
         clearInterval(obj.timer);
     }
     obj.style.left = obj.offsetLeft + step + 'px';
 },30);
}
 var box1 = document.querySelector('.box1');
 var btn = document.querySelectorAll('button')
 btn[0].addEventListener('click',function(){
     animate(box1,400);
 })
  btn[1].addEventListener('click',function(){
     animate(box1,700);
 })

The effect is:

At this time, we find that when we move forward, the element can accurately reach the target position, and the element can also achieve the effect of moving between two pixels, but the position reached when moving backward is not the target position. This is because our element is moving in the opposite direction when moving backward. At this time, we should also round the step length to the opposite position, that is, round it down.

At this time, we should judge the step length condition. If the step length is greater than zero, round it up. If the step length is less than zero, round it down. The adjusted step length formula is:

 var step = (target - obj.offsetLeft)/10;
 step > 0 ? Math.ceil(step) : Math.floor(step);

Now let’s take a look at the effect:

The problem is solved.

But at this point we have simply implemented the movement of an element between two locations. What if we want to change the color after it moves? We can do this by adding a callback function to the animation function.

6. Add callback function to animation function

Callback function principle: the function can be used as a parameter. Pass this function as a parameter to another function. When that function is executed, the passed function is executed again. This process is called callback.

The callback function is written at the location where the timer ends.

The specific implementation code is:

 function animate(obj,target,callback){
            clearInterval(obj.timer)
            obj.timer = setInterval(function(){
                var step = (target - obj.offsetLeft)/10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
            if(obj.offsetLeft == target){
                clearInterval(obj.timer);
                if(callback){
                    callback();
                } 
            }
            obj.style.left = obj.offsetLeft + step + 'px';
            },30);
        }
        var box1 = document.querySelector('.box1');
        var btn = document.querySelectorAll('button');
       btn[0].addEventListener('click',function(){
            animate(box1,400,function(){
                box1.style.backgroundColor = 'pink';
            });
        })
        btn[1].addEventListener('click',function(){
            animate(box1,700,function(){
                box1.style.backgroundColor = 'red';
            });
        })

The effect is:

The above is the encapsulation of the animation function. When it is used specifically, we can encapsulate it into a js file and directly reference it when needed.

This is the end of this article about the detailed explanation of JavaScript animation function encapsulation. For more relevant JavaScript animation function encapsulation content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Encapsulation method of JavaScript slow motion animation function
  • JavaScript speed-changing animation function encapsulation adds any number of attributes
  • JavaScript implements left and right slow animation function
  • A simple example of implementing the jQuery animate() animation effect with native JS

<<:  base target="" specifies the target of the base link to open the frame

>>:  Linux Network System Introduction

Recommend

Zabbix monitors the process of Linux system services

Zabbix automatically discovers rules to monitor s...

How to create a database in navicat 8 for mysql

When developing a website, you often need to use ...

Let’s talk in detail about how JavaScript affects DOM tree construction

Table of contents Document Object Model (DOM) DOM...

Vue uses Baidu Maps to realize city positioning

This article shares the specific code of Vue usin...

Docker link realizes container interconnection

Table of contents 1.1. Network access between con...

Detailed explanation of HTML table inline format

Inline format <colgroup>...</colgroup>...

A brief analysis of the function calling process under the ARM architecture

Table of contents 1. Background knowledge 1. Intr...

Vue implements automatic jump to login page when token expires

The project was tested these days, and the tester...

When MySQL is upgraded to 5.7, WordPress reports error 1067 when importing data

I recently upgraded MySQL to 5.7, and WordPress r...

Centos6.9 installation Mysql5.7.18 step record

Installation sequence rpm -ivh mysql-community-co...

CSS3 achieves conic-gradient effect

grammar: background-image: conic-gradient(from an...

Detailed explanation of various HTTP return status codes

When a request is sent to your server to display ...

How to convert rows to columns in MySQL

MySQL row to column operation The so-called row-t...

Summary of solutions to common Linux problems

1. Connect Centos7 under VMware and set a fixed I...