📜 ⬆️ ⬇️

Animations against lags, or the best battle that was not

image

Have you noticed, when you just open a website, the first seconds everything slows down? Scrolling somehow does not work smoothly, parallaxes jump, and it seems that the lion's share of frames was cut out from the animation. But very soon everything will be normal. Did not notice this? Take a look at the demo page of the plugin , and immediately understand what I mean.

The problem is that the dynamics can not work normally while the page lags. As a solution, I suggest the plugin “Afterlag.js”. The plugin allows you to track the event of the end of the lag. Lags have passed, turn on the animation, it will not slow down. In the meantime, the page lags, there is nothing to run the dynamics, only the view spoil.

How to use


Connect the JS file with the plugin, write:
$.afterlag(function() { console.log(',  !'); }); 

As soon as the page runs out of lags, your console will begin to express joy about this. If jQuery do not want to use, connect the native plugin and write:
 afterlag = new Afterlag(); afterlag.do(function() { console.log(',  !'); }); 

The result will be the same.
')
This is the simplest thing a plugin can do. In fact, the plugin has an API and a bunch of other ways to call, all this is fully described in the readme repository on the githaba . There are also ways to connect, links to CDN, the name of the plugin in bower and the npm module.

Why everything slows down


Let's see why the animation lags at the start. Consider the animation of the roundels on the demo page, its task is to smoothly go up, then go down.

Motion animation is implemented using the animate jakery library method. We animate the only CSS attribute top, its value is determined by a given function of time. By running the animation, the jakery tries to update the value of top every moment. If jakery really did update this value so often, the animation would be smartly smooth. But jQuery fails.

It does not work, because JS executes all the events in one thread. JS runs through the list of things to do and does it. Not all cases are at the end of the list. If you clicked somewhere, thereby triggering an event, the task of its execution is stuck at the top of the list in order to execute it as soon as possible. Rather, but not at the same moment. If you don’t grasp the point, you can read this short article , it tells in more detail how intervals and timeouts work in the light of JS single-threaded. And do not forget that in fact all tasks are performed by the browser, and the to-do list transferred from JS is also diluted with other tasks of the browser.

So, jakery wanted to update the top value for our rounder more often. But at the time of loading the page there were a lot of more priority cases: to render a page, to pull up videos from YouTube and so on. The poor browser was so busy that it managed to update the top value only once every 200–300 milliseconds. During this time, the round shape, on the basis of a given function, has already shifted pixels by 60. As a result, the circle does not smoothly fit its new position, but teleports there, creating a sense of lost frames, jerking and inhibition. Then, when the browser completed all its important affairs, it began to update the top value for the circle in a timely manner, and the animation became even.

How does “Afterlag.js” work


Afterlag will find out when the browser will no longer be so busy and will be able to quite often execute the code necessary for smooth animation playback. Let's say we are satisfied if the animation task is executed at least once every 50 milliseconds ( frequency ). During the initialization, the after-tag will remember the current time and start the interval of 50 ms. After 50 ms, we again find out the current time. We compare the current time with the previously recorded, if indeed 50 ms has passed, then the lags are over. And if in fact not 50 ms passed, but, say, 100 ms, then the page is still lagged and the procedure must be repeated until the interval starts working as we expect.

Only I wrote the plugin according to the above scheme and decided that it is quite efficient. But no. It happens that the interval just got lucky. It happened so that the first two iterations, the expected value of the past time differed from the actual past, the third iteration coincided, and the fourth again differed. We solve the problem in the forehead: let the expected time coincide with the actually passed 10 times in a row ( iterations ).

“Well, now everything is surely working as it should,” I thought, and I was mistaken. If you set not large enough values ​​for ( frequency ) and ( iterations ), for example, 30 and 3, in the first moments it may happen that the browser was not busy for the first 90 ms, i.e. 3 iterations of 30 ms each, the afterlag decided that the lag ran out, and they were just beginning. We decide again to the forehead: set the value of the time during which it is impossible to trust the after-tag ( delay ) with a margin of 200 ms.

Update article (March 12, 2015):
On the advice of webmasterx , a setting has been added ( need_lags ). I quote the documentation: “If false afterlag will work either if the lags run out or if they don't even start. A value of true allows the afterlag to work only after the end of the lags, that is, if there were no lags, the aftelag will not work. Setting the value to true do not forget to also set the value for the timeout , in the opposite case, if there is no lag, the afterlag will not work. ”
The end of the update.

Now everything works as it should. There is one more parameter that I took into account immediately, but decided to say just now. This is the permissible error when reconciling the expected and actual past time ( scatter ) - 5 ms. We will not be very strict with the browser.

All numbers specified in this section are used by the default after-tag, but can be changed by the developer during initialization.

Conclusion


Animation implemented using CSS is much less subject to this kind of lag. Afterlag is only useful when site dynamics are associated with JS, including smooth parallaxes, animation of scrolling and so on. I would be interested to know your opinion on the usefulness of the plugin.

Afterlag most often works correctly, but does not give a 100% guarantee. When changing the settings, you have to catch the balance: greater reliability and a longer wait, or lower reliability and a shorter wait. The plugin will appeal to those developers who love when the speaker works beautifully and in the way it was intended.

Source: https://habr.com/ru/post/252637/


All Articles