banner



How To Create Animation Effects In Javascript

JavaScript animations can handle things that CSS can't.

For instance, moving along a complex path, with a timing part unlike from Bezier curves, or an animation on a canvas.

Using setInterval

An animation tin can be implemented equally a sequence of frames – normally minor changes to HTML/CSS properties.

For case, changing way.left from 0px to 100px moves the element. And if we increase it in setInterval, changing by 2px with a tiny delay, like fifty times per second, then it looks smooth. That'due south the aforementioned principle every bit in the movie house: 24 frames per second is plenty to make it look shine.

The pseudo-code tin can look similar this:

            let timer = setInterval(office() {   if (animation complete) clearInterval(timer);   else increase style.left by 2px }, 20); // change by 2px every 20ms, about 50 frames per second          

More complete case of the animation:

            let start = Date.now(); // recall start time  let timer = setInterval(function() {   // how much time passed from the start?   permit timePassed = Date.now() - start;    if (timePassed >= 2000) {     clearInterval(timer); // end the blitheness after two seconds     render;   }    // depict the animation at the moment timePassed   draw(timePassed);  }, xx);  // every bit timePassed goes from 0 to 2000 // left gets values from 0px to 400px function draw(timePassed) {   train.style.left = timePassed / 5 + 'px'; }          

Click for the demo:

            <!DOCTYPE HTML> <html>  <caput>   <style>     #train {       position: relative;       cursor: pointer;     }   </style> </head>  <body>    <img id="railroad train" src="https://js.cx/clipart/railroad train.gif">     <script>     railroad train.onclick = function() {       let start = Appointment.now();        let timer = setInterval(function() {         permit timePassed = Engagement.at present() - start;          train.style.left = timePassed / 5 + 'px';          if (timePassed > 2000) clearInterval(timer);        }, xx);     }   </script>   </body>  </html>          

Using requestAnimationFrame

Permit's imagine we take several animations running simultaneously.

If we run them separately, then even though each one has setInterval(..., 20), so the browser would have to repaint much more ofttimes than every 20ms.

That'south because they take different starting time, so "every 20ms" differs between different animations. The intervals are not aligned. So we'll accept several independent runs within 20ms.

In other words, this:

            setInterval(function() {   animate1();   animate2();   animate3(); }, 20)          

…Is lighter than three independent calls:

            setInterval(animate1, 20); // contained animations setInterval(animate2, 20); // in unlike places of the script setInterval(animate3, 20);          

These several independent redraws should be grouped together, to make the redraw easier for the browser and hence load less CPU load and expect smoother.

There's one more thing to keep in listen. Sometimes CPU is overloaded, or there are other reasons to redraw less ofttimes (similar when the browser tab is subconscious), so nosotros actually shouldn't run it every 20ms.

But how do we know about that in JavaScript? There's a specification Blitheness timing that provides the role requestAnimationFrame. Information technology addresses all these bug and even more.

The syntax:

            permit requestId = requestAnimationFrame(callback)          

That schedules the callback part to run in the closest fourth dimension when the browser wants to exercise blitheness.

If we do changes in elements in callback then they volition be grouped together with other requestAnimationFrame callbacks and with CSS animations. So there will be one geometry recalculation and repaint instead of many.

The returned value requestId can be used to cancel the call:

            // cancel the scheduled execution of callback cancelAnimationFrame(requestId);          

The callback gets one argument – the time passed from the beginning of the page load in milliseconds. This fourth dimension tin also exist obtained past calling performance.now().

Usually callback runs very soon, unless the CPU is overloaded or the laptop battery is near discharged, or there's some other reason.

The code below shows the time betwixt kickoff 10 runs for requestAnimationFrame. Commonly it'south 10-20ms:

            <script>   let prev = functioning.now();   let times = 0;    requestAnimationFrame(part measure(time) {     document.torso.insertAdjacentHTML("beforeEnd", Math.floor(fourth dimension - prev) + " ");     prev = fourth dimension;      if (times++ < 10) requestAnimationFrame(measure);   }) </script>          

Structured animation

At present we can make a more than universal animation function based on requestAnimationFrame:

            part animate({timing, describe, elapsing}) {    let start = performance.now();    requestAnimationFrame(function breathing(time) {     // timeFraction goes from 0 to i     let timeFraction = (time - get-go) / duration;     if (timeFraction > 1) timeFraction = 1;      // calculate the current animation state     let progress = timing(timeFraction)      depict(progress); // draw it      if (timeFraction < i) {       requestAnimationFrame(breathing);     }    }); }          

Function animate accepts 3 parameters that essentially describes the animation:

duration

Total time of animation. Like, thou.

timing(timeFraction)

Timing function, like CSS-holding transition-timing-part that gets the fraction of fourth dimension that passed (0 at start, 1 at the end) and returns the animation completion (similar y on the Bezier bend).

For case, a linear function means that the animation goes on uniformly with the same speed:

                part linear(timeFraction) {   return timeFraction; }              

Its graph:

That'due south simply like transition-timing-function: linear. At that place are more interesting variants shown below.

draw(progress)

The function that takes the blitheness completion country and draws it. The value progress=0 denotes the beginning animation state, and progress=1 – the end country.

This is that function that actually draws out the blitheness.

It can move the chemical element:

                role depict(progress) {   railroad train.style.left = progress + 'px'; }              

…Or do anything else, we tin animate annihilation, in any way.

Allow'due south animate the chemical element width from 0 to 100% using our part.

Click on the chemical element for the demo:

              function animate({duration, draw, timing}) {    let start = performance.now();    requestAnimationFrame(role animate(time) {     permit timeFraction = (time - beginning) / duration;     if (timeFraction > 1) timeFraction = 1;      let progress = timing(timeFraction)      draw(progress);      if (timeFraction < i) {       requestAnimationFrame(animate);     }    }); }            
              <!DOCTYPE HTML> <html>  <head>   <meta charset="utf-eight">   <manner>     progress {       width: 5%;     }   </mode>   <script src="animate.js"></script> </head>  <body>     <progress id="elem"></progress>    <script>     elem.onclick = function() {       animate({         duration: k,         timing: function(timeFraction) {           return timeFraction;         },         draw: role(progress) {           elem.manner.width = progress * 100 + '%';         }       });     };   </script>   </trunk>  </html>            

The code for it:

            animate({   elapsing: 1000,   timing(timeFraction) {     return timeFraction;   },   draw(progress) {     elem.style.width = progress * 100 + '%';   } });          

Unlike CSS animation, nosotros tin can make whatever timing function and any drawing role hither. The timing part is not limited by Bezier curves. And describe can go across properties, create new elements for like fireworks animation or something.

Timing functions

Nosotros saw the simplest, linear timing role in a higher place.

Let's run into more than of them. We'll try movement animations with different timing functions to see how they work.

Ability of n

If we want to speed up the animation, we can use progress in the ability n.

For example, a parabolic curve:

            function quad(timeFraction) {   return Math.pow(timeFraction, 2) }          

The graph:

Meet in action (click to activate):

…Or the cubic curve or even greater northward. Increasing the power makes it speed up faster.

Hither's the graph for progress in the power 5:

In activity:

The arc

Function:

            function circ(timeFraction) {   return 1 - Math.sin(Math.acos(timeFraction)); }          

The graph:

Back: bow shooting

This function does the "bow shooting". First nosotros "pull the bowstring", and then "shoot".

Unlike previous functions, it depends on an boosted parameter x, the "elasticity coefficient". The distance of "bowstring pulling" is defined past it.

The code:

            function back(ten, timeFraction) {   render Math.pw(timeFraction, 2) * ((x + 1) * timeFraction - x) }          

The graph for x = 1.5:

For animation we use information technology with a specific value of ten. Case for x = 1.5:

Bounce

Imagine we are dropping a brawl. It falls down, so bounces back a few times and stops.

The bounce function does the same, simply in the reverse order: "bouncing" starts immediately. It uses few special coefficients for that:

            function bounce(timeFraction) {   for (let a = 0, b = one; one; a += b, b /= 2) {     if (timeFraction >= (7 - 4 * a) / xi) {       render -Math.pow((xi - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, ii)     }   } }          

In action:

Elastic animation

One more "elastic" function that accepts an boosted parameter ten for the "initial range".

            role rubberband(ten, timeFraction) {   return Math.pow(two, 10 * (timeFraction - 1)) * Math.cos(twenty * Math.PI * x / three * timeFraction) }          

The graph for x=one.five:

In activity for ten=1.5:

Reversal: ease*

So we accept a collection of timing functions. Their straight application is called "easeIn".

Sometimes we need to bear witness the animation in the reverse guild. That's done with the "easeOut" transform.

easeOut

In the "easeOut" fashion the timing function is put into a wrapper timingEaseOut:

            timingEaseOut(timeFraction) = one - timing(1 - timeFraction)          

In other words, we have a "transform" function makeEaseOut that takes a "regular" timing function and returns the wrapper around information technology:

            // accepts a timing function, returns the transformed variant function makeEaseOut(timing) {   return function(timeFraction) {     render one - timing(1 - timeFraction);   } }          

For instance, we can have the bounce function described above and apply information technology:

            let bounceEaseOut = makeEaseOut(bounce);          

Then the bounciness will exist non in the beginning, merely at the end of the blitheness. Looks even meliorate:

              #brick {   width: 40px;   acme: 20px;   groundwork: #EE6B47;   position: relative;   cursor: pointer; }  #path {   outline: 1px solid #E8C48E;   width: 540px;   height: 20px; }            
              <!DOCTYPE HTML> <html>  <head>   <meta charset="utf-viii">   <link rel="stylesheet" href="style.css">   <script src="https://js.cx/libs/animate.js"></script> </head>  <body>     <div id="path">     <div id="brick"></div>   </div>    <script>     office makeEaseOut(timing) {       return function(timeFraction) {         render ane - timing(one - timeFraction);       }     }      function bounce(timeFraction) {       for (let a = 0, b = 1; 1; a += b, b /= 2) {         if (timeFraction >= (seven - 4 * a) / 11) {           return -Math.prisoner of war((eleven - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2)         }       }     }      allow bounceEaseOut = makeEaseOut(bounce);      brick.onclick = function() {       animate({         duration: 3000,         timing: bounceEaseOut,         draw: function(progress) {           brick.fashion.left = progress * 500 + 'px';         }       });     };   </script>   </torso>  </html>            

Here we can see how the transform changes the beliefs of the function:

If there's an blitheness result in the beginning, like bouncing – it will be shown at the end.

In the graph in a higher place the regular bounciness has the cherry-red colour, and the easeOut bounce is blue.

  • Regular bounce – the object bounces at the bottom, then at the stop sharply jumps to the top.
  • Afterward easeOut – it beginning jumps to the pinnacle, then bounces there.

easeInOut

Nosotros also tin bear witness the issue both in the beginning and the end of the blitheness. The transform is called "easeInOut".

Given the timing function, nosotros calculate the animation country like this:

            if (timeFraction <= 0.5) { // start one-half of the blitheness   render timing(ii * timeFraction) / ii; } else { // 2d one-half of the animation   return (2 - timing(2 * (ane - timeFraction))) / 2; }          

The wrapper code:

            function makeEaseInOut(timing) {   return function(timeFraction) {     if (timeFraction < .5)       render timing(2 * timeFraction) / ii;     else       return (2 - timing(2 * (1 - timeFraction))) / ii;   } }  bounceEaseInOut = makeEaseInOut(bounce);          

In action, bounceEaseInOut:

              #brick {   width: 40px;   height: 20px;   background: #EE6B47;   position: relative;   cursor: pointer; }  #path {   outline: 1px solid #E8C48E;   width: 540px;   height: 20px; }            
              <!DOCTYPE HTML> <html>  <head>   <meta charset="utf-8">   <link rel="stylesheet" href="style.css">   <script src="https://js.cx/libs/animate.js"></script> </caput>  <body>     <div id="path">     <div id="brick"></div>   </div>    <script>     function makeEaseInOut(timing) {       render role(timeFraction) {         if (timeFraction < .5)           render timing(ii * timeFraction) / 2;         else           return (2 - timing(2 * (1 - timeFraction))) / ii;       }     }       function bounciness(timeFraction) {       for (permit a = 0, b = 1; 1; a += b, b /= 2) {         if (timeFraction >= (7 - 4 * a) / xi) {           return -Math.prisoner of war((11 - 6 * a - 11 * timeFraction) / four, 2) + Math.pow(b, two)         }       }     }      allow bounceEaseInOut = makeEaseInOut(bounce);      brick.onclick = role() {       animate({         duration: 3000,         timing: bounceEaseInOut,         depict: function(progress) {           brick.style.left = progress * 500 + 'px';         }       });     };   </script>   </body>  </html>            

The "easeInOut" transform joins 2 graphs into one: easeIn (regular) for the first one-half of the blitheness and easeOut (reversed) – for the 2d part.

The effect is clearly seen if we compare the graphs of easeIn, easeOut and easeInOut of the circ timing function:

  • Red is the regular variant of circ (easeIn).
  • GreeneaseOut.
  • BlueeaseInOut.

As nosotros can see, the graph of the first half of the animation is the scaled down easeIn, and the second half is the scaled downward easeOut. As a result, the animation starts and finishes with the same effect.

More interesting "draw"

Instead of moving the element we tin can practise something else. All we demand is to write the proper draw.

Here'due south the animated "billowy" text typing:

              textarea {   display: block;   edge: 1px solid #BBB;   color: #444;   font-size: 110%; }  push {   margin-top: 10px; }            
              <!DOCTYPE HTML> <html>  <caput>   <meta charset="utf-8">   <link rel="stylesheet" href="style.css">   <script src="https://js.cx/libs/animate.js"></script> </head>  <body>     <textarea id="textExample" rows="5" cols="threescore">He took his vorpal sword in hand: Long time the manxome foe he sought— So rested he past the Tumtum tree, And stood awhile in thought.   </textarea>    <button onclick="animateText(textExample)">Run the animated typing!</push>    <script>     function animateText(textArea) {       let text = textArea.value;       allow to = text.length,         from = 0;        breathing({         duration: 5000,         timing: bounce,         draw: function(progress) {           let result = (to - from) * progress + from;           textArea.value = text.substr(0, Math.ceil(result))         }       });     }       function bounce(timeFraction) {       for (allow a = 0, b = 1; one; a += b, b /= two) {         if (timeFraction >= (vii - four * a) / 11) {           return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, ii) + Math.prisoner of war(b, 2)         }       }     }   </script>   </body>  </html>            

Summary

For animations that CSS can't handle well, or those that need tight control, JavaScript can help. JavaScript animations should be implemented via requestAnimationFrame. That built-in method allows to setup a callback function to run when the browser volition be preparing a repaint. Usually that'due south very soon, but the verbal time depends on the browser.

When a folio is in the background, there are no repaints at all, and then the callback won't run: the animation will be suspended and won't eat resources. That's great.

Hither's the helper animate role to setup about animations:

            role animate({timing, draw, elapsing}) {    let start = performance.now();    requestAnimationFrame(function breathing(time) {     // timeFraction goes from 0 to 1     let timeFraction = (time - get-go) / duration;     if (timeFraction > i) timeFraction = 1;      // summate the current animation state     let progress = timing(timeFraction);      depict(progress); // draw it      if (timeFraction < 1) {       requestAnimationFrame(animate);     }    }); }          

Options:

  • duration – the total animation time in ms.
  • timing – the function to calculate animation progress. Gets a time fraction from 0 to 1, returns the animation progress, usually from 0 to one.
  • draw – the office to depict the animation.

Surely we could improve it, add more than bells and whistles, simply JavaScript animations are not applied on a daily footing. They are used to exercise something interesting and not-standard. So yous'd want to add the features that you lot need when y'all need them.

JavaScript animations tin can apply any timing function. We covered a lot of examples and transformations to brand them even more versatile. Different CSS, nosotros are not limited to Bezier curves here.

The same is about describe: we can animate anything, not only CSS properties.

Source: https://javascript.info/js-animation

Posted by: goodmancrooking1973.blogspot.com

0 Response to "How To Create Animation Effects In Javascript"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel