How To Use Animate Function In Javascript
JavaScript animations tin handle things that CSS tin't.
For instance, moving along a complex path, with a timing role different from Bezier curves, or an animation on a canvas.
Using setInterval
An blitheness tin be implemented equally a sequence of frames – usually pocket-sized changes to HTML/CSS properties.
For instance, changing manner.left
from 0px
to 100px
moves the element. And if we increase information technology in setInterval
, irresolute by 2px
with a tiny delay, like l times per 2nd, so it looks smooth. That'south the aforementioned principle as in the cinema: 24 frames per second is enough to make it expect polish.
The pseudo-code can look like this:
let timer = setInterval(function() { if (animation consummate) clearInterval(timer); else increase style.left by 2px }, 20); // change past 2px every 20ms, about 50 frames per second
More complete example of the animation:
let start = Engagement.at present(); // remember get-go time allow timer = setInterval(function() { // how much time passed from the start? let timePassed = Appointment.at present() - start; if (timePassed >= 2000) { clearInterval(timer); // terminate the animation afterward 2 seconds return; } // draw the animation at the moment timePassed depict(timePassed); }, 20); // equally timePassed goes from 0 to 2000 // left gets values from 0px to 400px function depict(timePassed) { railroad train.style.left = timePassed / 5 + 'px'; }
Click for the demo:
<!DOCTYPE HTML> <html> <head> <manner> #train { position: relative; cursor: pointer; } </style> </head> <body> <img id="train" src="https://js.cx/clipart/train.gif"> <script> train.onclick = function() { allow get-go = Appointment.now(); permit timer = setInterval(function() { let timePassed = Engagement.now() - get-go; railroad train.style.left = timePassed / v + 'px'; if (timePassed > 2000) clearInterval(timer); }, 20); } </script> </body> </html>
Using requestAnimationFrame
Let's imagine we take several animations running simultaneously.
If we run them separately, then even though each one has setInterval(..., 20)
, then the browser would have to repaint much more than often than every 20ms
.
That'south because they have different starting time, then "every 20ms" differs between unlike animations. The intervals are not aligned. So we'll take 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 different 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 await smoother.
There's 1 more thing to continue in mind. Sometimes CPU is overloaded, or there are other reasons to redraw less often (like when the browser tab is subconscious), so we really shouldn't run information technology every 20ms
.
Merely how practice we know virtually that in JavaScript? There's a specification Animation timing that provides the function requestAnimationFrame
. Information technology addresses all these issues and even more than.
The syntax:
permit requestId = requestAnimationFrame(callback)
That schedules the callback
office to run in the closest time when the browser wants to do animation.
If we do changes in elements in callback
then they will be grouped together with other requestAnimationFrame
callbacks and with CSS animations. And then there will be one geometry recalculation and repaint instead of many.
The returned value requestId
can exist 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 time can as well be obtained by calling operation.at present().
Usually callback
runs very soon, unless the CPU is overloaded or the laptop battery is near discharged, or in that location's some other reason.
The code beneath shows the fourth dimension between first 10 runs for requestAnimationFrame
. Usually information technology's 10-20ms:
<script> let prev = operation.now(); let times = 0; requestAnimationFrame(function measure(fourth dimension) { document.body.insertAdjacentHTML("beforeEnd", Math.floor(time - prev) + " "); prev = time; if (times++ < 10) requestAnimationFrame(measure); }) </script>
Structured animation
At present we can make a more universal blitheness role based on requestAnimationFrame
:
function animate({timing, depict, duration}) { let start = performance.at present(); requestAnimationFrame(role animate(fourth dimension) { // timeFraction goes from 0 to i permit timeFraction = (time - start) / elapsing; if (timeFraction > one) timeFraction = ane; // calculate the current animation state let progress = timing(timeFraction) describe(progress); // draw information technology if (timeFraction < 1) { requestAnimationFrame(animate); } }); }
Office breathing
accepts 3 parameters that essentially describes the blitheness:
-
elapsing
-
Total time of animation. Like,
chiliad
. -
timing(timeFraction)
-
Timing office, like CSS-property
transition-timing-function
that gets the fraction of time that passed (0
at start,one
at the end) and returns the animation completion (likey
on the Bezier curve).For instance, a linear function means that the animation goes on uniformly with the same speed:
part linear(timeFraction) { return timeFraction; }
Its graph:
That's but similar
transition-timing-function: linear
. At that place are more interesting variants shown beneath. -
draw(progress)
-
The function that takes the blitheness completion country and draws it. The value
progress=0
denotes the offset animation state, andprogress=i
– the stop state.This is that function that actually draws out the blitheness.
It tin move the chemical element:
function draw(progress) { train.style.left = progress + 'px'; }
…Or do anything else, nosotros can animate annihilation, in any mode.
Let'due south animate the element width
from 0
to 100%
using our function.
Click on the element for the demo:
office animate({elapsing, draw, timing}) { let start = functioning.now(); requestAnimationFrame(function animate(time) { permit timeFraction = (time - start) / duration; if (timeFraction > 1) timeFraction = i; allow progress = timing(timeFraction) describe(progress); if (timeFraction < ane) { requestAnimationFrame(animate); } }); }
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <style> progress { width: 5%; } </way> <script src="breathing.js"></script> </caput> <body> <progress id="elem"></progress> <script> elem.onclick = function() { animate({ elapsing: 1000, timing: function(timeFraction) { return timeFraction; }, describe: function(progress) { elem.manner.width = progress * 100 + '%'; } }); }; </script> </body> </html>
The code for information technology:
animate({ elapsing: yard, timing(timeFraction) { return timeFraction; }, draw(progress) { elem.way.width = progress * 100 + '%'; } });
Dissimilar CSS animation, nosotros tin can make any timing role and any drawing function here. The timing function is not express past Bezier curves. And draw
can go beyond backdrop, create new elements for like fireworks animation or something.
Timing functions
We saw the simplest, linear timing part above.
Let'southward see more of them. We'll try movement animations with different timing functions to run across how they piece of work.
Power of n
If we want to speed up the animation, we can use progress
in the power n
.
For instance, a parabolic bend:
function quad(timeFraction) { render Math.pow(timeFraction, 2) }
The graph:
See in action (click to activate):
…Or the cubic bend or even greater northward
. Increasing the power makes information technology speed up faster.
Here'south the graph for progress
in the ability 5
:
In activity:
The arc
Office:
role circ(timeFraction) { return 1 - Math.sin(Math.acos(timeFraction)); }
The graph:
Back: bow shooting
This function does the "bow shooting". Beginning nosotros "pull the bowstring", and and then "shoot".
Unlike previous functions, it depends on an additional parameter x
, the "elasticity coefficient". The distance of "bowstring pulling" is defined by it.
The lawmaking:
function back(x, timeFraction) { return Math.pw(timeFraction, two) * ((10 + 1) * timeFraction - x) }
The graph for x = one.5
:
For animation we use information technology with a specific value of 10
. Instance for x = i.5
:
Bounciness
Imagine nosotros are dropping a ball. Information technology falls down, then bounces dorsum a few times and stops.
The bounce
office does the same, but in the contrary order: "bouncing" starts immediately. Information technology uses few special coefficients for that:
office bounce(timeFraction) { for (allow a = 0, b = 1; ane; a += b, b /= ii) { if (timeFraction >= (7 - 4 * a) / eleven) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pw(b, 2) } } }
In action:
Elastic animation
One more than "elastic" role that accepts an additional parameter x
for the "initial range".
function elastic(x, timeFraction) { return Math.pow(ii, 10 * (timeFraction - 1)) * Math.cos(20 * Math.PI * x / 3 * timeFraction) }
The graph for x=1.5
:
In action for x=1.five
:
Reversal: ease*
So we have a collection of timing functions. Their straight application is chosen "easeIn".
Sometimes we need to testify the blitheness in the reverse lodge. That's washed with the "easeOut" transform.
easeOut
In the "easeOut" mode the timing
role is put into a wrapper timingEaseOut
:
timingEaseOut(timeFraction) = 1 - timing(i - timeFraction)
In other words, we accept a "transform" function makeEaseOut
that takes a "regular" timing function and returns the wrapper effectually information technology:
// accepts a timing function, returns the transformed variant role makeEaseOut(timing) { return function(timeFraction) { return i - timing(1 - timeFraction); } }
For instance, nosotros tin can accept the bounciness
part described above and apply it:
let bounceEaseOut = makeEaseOut(bounce);
Then the bounce will be not in the showtime, merely at the cease of the animation. Looks even better:
#brick { width: 40px; pinnacle: 20px; groundwork: #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="way.css"> <script src="https://js.cx/libs/animate.js"></script> </caput> <trunk> <div id="path"> <div id="brick"></div> </div> <script> part makeEaseOut(timing) { render function(timeFraction) { return 1 - timing(i - timeFraction); } } role bounciness(timeFraction) { for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - four * a) / 11) { return -Math.prisoner of war((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, two) } } } let bounceEaseOut = makeEaseOut(bounce); brick.onclick = function() { breathing({ elapsing: 3000, timing: bounceEaseOut, draw: function(progress) { brick.style.left = progress * 500 + 'px'; } }); }; </script> </torso> </html>
Here we tin see how the transform changes the behavior of the role:
If at that place's an animation effect in the beginning, like bouncing – it will be shown at the cease.
In the graph above the regular bounce has the red color, and the easeOut bounce is blue.
- Regular bounce – the object bounces at the bottom, so at the end sharply jumps to the pinnacle.
- Subsequently
easeOut
– it outset jumps to the summit, then bounces there.
easeInOut
We also tin can show the effect both in the showtime and the stop of the blitheness. The transform is chosen "easeInOut".
Given the timing office, we calculate the animation land like this:
if (timeFraction <= 0.five) { // offset half of the blitheness return timing(2 * timeFraction) / 2; } else { // second half of the animation return (2 - timing(2 * (ane - timeFraction))) / ii; }
The wrapper code:
function makeEaseInOut(timing) { render function(timeFraction) { if (timeFraction < .5) return timing(two * timeFraction) / 2; else return (2 - timing(2 * (1 - timeFraction))) / 2; } } bounceEaseInOut = makeEaseInOut(bounce);
In action, bounceEaseInOut
:
#brick { width: 40px; height: 20px; background: #EE6B47; position: relative; cursor: arrow; } #path { outline: 1px solid #E8C48E; width: 540px; peak: 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> function makeEaseInOut(timing) { return office(timeFraction) { if (timeFraction < .5) render timing(two * timeFraction) / ii; else return (2 - timing(two * (1 - timeFraction))) / ii; } } function bounce(timeFraction) { for (let a = 0, b = 1; 1; a += b, b /= ii) { if (timeFraction >= (seven - iv * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / iv, 2) + Math.prisoner of war(b, two) } } } permit bounceEaseInOut = makeEaseInOut(bounce); brick.onclick = function() { animate({ duration: 3000, timing: bounceEaseInOut, draw: function(progress) { brick.style.left = progress * 500 + 'px'; } }); }; </script> </trunk> </html>
The "easeInOut" transform joins two graphs into one: easeIn
(regular) for the first one-half of the animation and easeOut
(reversed) – for the second part.
The effect is clearly seen if we compare the graphs of easeIn
, easeOut
and easeInOut
of the circ
timing function:
- Reddish is the regular variant of
circ
(easeIn
). - Light-green –
easeOut
. - Blue –
easeInOut
.
As we tin can see, the graph of the showtime one-half of the animation is the scaled downwardly easeIn
, and the second half is the scaled down easeOut
. Equally a result, the animation starts and finishes with the aforementioned issue.
More interesting "describe"
Instead of moving the chemical element we can do something else. All we need is to write the proper depict
.
Here'southward the animated "bouncing" text typing:
textarea { brandish: block; border: 1px solid #BBB; color: #444; font-size: 110%; } button { margin-top: 10px; }
<!DOCTYPE HTML> <html> <head> <meta charset="utf-eight"> <link rel="stylesheet" href="style.css"> <script src="https://js.cx/libs/animate.js"></script> </head> <body> <textarea id="textExample" rows="5" cols="lx">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> <push onclick="animateText(textExample)">Run the animated typing!</button> <script> function animateText(textArea) { permit text = textArea.value; let to = text.length, from = 0; animate({ duration: 5000, timing: bounce, draw: part(progress) { let result = (to - from) * progress + from; textArea.value = text.substr(0, Math.ceil(result)) } }); } part bounce(timeFraction) { for (let a = 0, b = 1; 1; a += b, b /= ii) { if (timeFraction >= (vii - 4 * a) / xi) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / four, 2) + Math.pow(b, 2) } } } </script> </torso> </html>
Summary
For animations that CSS can't handle well, or those that need tight command, JavaScript tin can help. JavaScript animations should be implemented via requestAnimationFrame
. That built-in method allows to setup a callback role to run when the browser will be preparing a repaint. Usually that'southward very shortly, but the exact time depends on the browser.
When a page is in the background, in that location are no repaints at all, so the callback won't run: the animation will be suspended and won't swallow resource. That's great.
Here's the helper animate
function to setup most animations:
function animate({timing, draw, duration}) { let start = performance.now(); requestAnimationFrame(office breathing(time) { // timeFraction goes from 0 to 1 let timeFraction = (time - showtime) / duration; if (timeFraction > 1) timeFraction = i; // calculate the current animation land permit progress = timing(timeFraction); describe(progress); // draw it if (timeFraction < 1) { requestAnimationFrame(breathing); } }); }
Options:
-
duration
– the total animation time in ms. -
timing
– the role to summate animation progress. Gets a time fraction from 0 to one, returns the blitheness progress, usually from 0 to one. -
draw
– the function to draw the blitheness.
Surely we could improve it, add more bells and whistles, but JavaScript animations are not practical on a daily basis. They are used to practice something interesting and non-standard. So you'd desire to add the features that yous need when you need them.
JavaScript animations can use any timing function. We covered a lot of examples and transformations to make them even more versatile. Unlike CSS, we are not limited to Bezier curves here.
The aforementioned is about draw
: we can animate anything, not just CSS properties.
Source: https://javascript.info/js-animation
Posted by: gaultgrabusereave1955.blogspot.com
0 Response to "How To Use Animate Function In Javascript"
Post a Comment