Animation against lags, or the best battle is the one that was not


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

The problem is that the dynamics cannot work properly while the page lags. As a solution, I propose the Afterlag.js plugin. The plugin allows you to track the event of the end of lags. The lags have passed, turn on the animation, it will not slow down. In the meantime, the page lags, there is nothing to start 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 you do not want to use jQuery, connect the native plugin and write:
afterlag = new Afterlag(); {
  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 of the repository on the github . There are also connection methods, links to CDN, the name of the plugin in bower and the npm module.

Why is everything slowing down

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

Motion tweens are implemented using the animate method of the jakery library. We animate the only CSS attribute top, its value is determined by a given function of time. Having launched the animation, the jakery tries to update the value of top every moment. If the jakery really succeeded in updating this value so often, then the animation would be chicly smooth. But jQuery fails.

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

So, the jakery wanted to update the value of top for our round piece more often. But at the time the page was loading, there were a lot of more priority matters: rendering a page, pulling up a YouTube video, and so on. The poor browser was so busy that he managed to update the top value only once every 200-300 milliseconds. During this time, based on the given function, the round circle has already shifted 60 pixels. As a result, the circle does not smoothly approach its new position, but is teleported there, creating the feeling of lost frames, twitching and inhibition. Then, when the browser completed all its important matters, it began to timely update the top value for the circle, and the animation became smooth.

How "Afterlag.js" Works

Afterlag will have to find out when the browser stops being so busy and can quite often execute the code necessary for smooth animation playback. Let's say it suits us if the animation task is executed at least once every 50 milliseconds ( frequency). After initialization, the afterlog 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 fixed, if 50 ms really passed, then the lags are over. And if, in fact, it was not 50 ms, but, say, 100 ms, then the page still lags and the procedure must be repeated until the interval starts working as we expect it to.

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

“Well, now everything probably works 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, at the first moments it may happen that the browser has not been busy for the first 90 ms, that is, 3 iterations of 30 ms, afterlag decided that the lags are over, but they actually just started. We decide again on the forehead: set the value of time during which you cannot trust the afterlag ( delay) with a margin of 200 ms.

Article update (March 12, 2015):
On the advice of webmasterx , the setting ( need_lags) was added . I quote the documentation: “If falseset, afterlag will work either if the lags run out, or if they don't even start. The value trueallows the afterlag to work only after the end of the lags, that is, if there were no lags, the aftertag will not work. When setting a value, truebe sure to also set the value fortimeout, otherwise, if there are no lags, the afterlog will not work. ”
End of update.

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

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


CSS animations are much less prone to this kind of lag. Afterlag is useful only when the site’s dynamics are related to JS, including smooth parallaxes, scroll animation, and more. 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 settings, you have to catch the balance: greater reliability and a longer wait, or less reliability and a shorter wait. The plugin will appeal to those developers who love when the dynamics work beautifully and the way it was intended.

Also popular now: