Animation of falling snow on Canvas is several times more effective than animation on DOM

  • Tutorial
. Compared to native JS on DOM elements, implementation of animated algorithms on Canvas is usually many times more productive. This is a well-known fact (but with features for a small number of particles, as it will be explained later), and he can find a way to implement everything that interferes with the traditional “under the snow”, but “falling snow” driven by rational users. In order to keep the load light, in recent years it has been considered a good form to “launch” snow on the site, barely noticeable, with a minimum number of snowflakes (5-15). There is an effect, and there is almost no load on the processor.

Therefore, while the NG is still a few daysstill winter, I propose to arrange a hackathon for the implementation of the best algorithms on canvas and their analogues on the DOM, taking as a basis mainly ancient native algorithms, which at maximum wrap themselves in the jQuery plugin to make it convenient to connect. Most of these algorithms do not balance the load on the processor or are done inefficiently, therefore, even with a small number of snowflakes, the processor is 100% loaded. Here is an example of a review article , where more than 10 implementations are considered, not all that are found in nature. In addition, we will consider a few favorites to get a foundation for the development of the algorithm and its implementation with good efficiency (we will get another 5-6 options). On this basis, you can build a revision. Github with 12 demos (links repeated below) and several algorithms.

As usual, the life of an article on Habré does not last more than 1.5 days, so you can’t count an effective stock. But after the New Year, different miracles happen: the flow of visitors falls, and random lunatics get a chance not to forget one article for 5 days. They bet on them.

It is better if it is tied to a lengthy process, for example, to the club of Anonymous Santa Clauses, entering which you can always get a binding to discuss and develop options for "falling snow" and at the same time it is not tied tightly to the holiday. The result is currently here: geekadm.ru/#/2015 , and of course there are intermediate experiments like 46.101.141.171/snow.html?v=4 - snow for HabraAdm with additional effects.

The preliminary "hackathon" was arranged by a pair of participants and (or) visitors to the club - (1) , (2) . As a result, it turned out up to 10 options on the engine with Canvas. Their number can be much larger, but free time is needed for everything, so the action has turned into an open one. For example, you can "screw" to the engine already written in 2003 a model of falling snowflakes by Peter Gehrig. Finalization in 2005-2006 shows on modern browsers that 20-30 snowflakes slightly load the processor (10-20%, depends on the power and video card; hereinafter we will talk about loading one processor corebecause JS is single-threaded), and according to the old forums, it was similar on older browsers like Opera 9 and IE6, but somewhat worse. On Canvas with the same algorithm, you could run 5 times more objects.


demo


Let's look into history and look at its course


Let's start from the beginning, from about 2002-2005. Javascript showed the ability to animate snowflakes falling. True, it turned out, and it was natural, the animation on the script is either unproductive or heavily loads the processor. Therefore, in those old days it was necessary either to save resources very much, or to load the processor to the maximum, 100% in the browser stream, (on 1 core) which slowed down the other tabs (in those browsers like Opera 9 where they were) and windows, and this caused a poorly hidden indignation of visitors to such pages.

After 8 years, a solution to this problem was found at the browser level. The main browsers, starting with Chrome, began to suspend script execution on invisible tabs. This helped not to interfere with viewing other windows and programs (but it does not pause when switching to another window, but only reduces the load if the window is not drawn on the screen or is partially visible). However, in connection with the mobile era, opening pages with loading animations is still not perceived positively.

But over the years, a more advanced animation mechanism has appeared - Canvas. It should be noted right away that another innovative mechanism - animations in CSS - does not help to save load, and they spend the processor energy exactly as much as animation on Javascript + DOM. That is, if you look for the best solution, you have to do it in Canvas.

Canvas, as will be seen in the examples, allows you to run a hundred snowflakes with a load of 30-40% for an average desktop computer or laptop. This is about 5 times more efficient than the best optimized JS + DOM algorithms can do.

As a tribute to history, let us consider the “classic” algorithms that are waiting in the wings for optimization and translation to Canvas.

A lot of algorithms are easy to find by searching on Github for words like “snowfall js”, “snow flakes js”. They will complement the good selection of 12 scripts with demo links mentioned above (or an expanded copy ).

Algorithm Overview with Examples


(When viewing pages with examples, be prepared for sometimes 100% loading of the processor core. When you show the link in the article, the load level is warned.)

Many algorithms, in addition to being inefficient, are not similar in behavior to the actual behavior of snowflakes. Probably, many remember the striking inconsistency of reality with the movement of snowflakes along a sinusoid. Once seen (or newer ), it is remembered for a long time as a negative example. Therefore, the task of the algorithm is to be not only effective, but also reflecting reality. (In terms of efficiency, the calculation of harmonic functions should also lose.)

Of the previously reviewed algorithms, two can be considered closest to reality - with random movements (you need to vary the speed, not the coordinates) and the mentioned Peter Gehrig algorithm (2003), in which the movement is controlled by 4 variables, and one of them is harmonically changing, which creates periodic effects of "twists". However, on this occasion, you can argue and add new implementations to the piggy bank.

From the found implementations of the P. Gehrig algorithm, a page with an example was found: www.softtime.ru/javascript/snow-falling.html. It is clear what is at stake. A small number of snowflakes (15-20) and now do not load processors much (10-20% for not weak laptops), works in Chrome and Firefox, although Opera 9, IE5 and 6 and some early Firefox are read in the support list. Of course, then they did not know about Canvas.

We summarize what we saw in the table, where we show:
*) the number of particles;
*) type of animation;
*) the presence of a sandbox for experiments;
*) processor load (MacBook, Firefox 43) (Chrome is usually% 10 more efficient);
*) comments about the features.

(The actual processor load data will differ from that indicated for different computers, for computers with different graphics cards and for mobile devices within wide limits. They are given for orientation for a medium-power laptop with integrated graphics.)

Let's look at the scripts using Canvas faster.
Not pure js Demo: 400x400, Snowman with Falling Snow
Particles per Demo: 100
Type: Canvas
Sandbox - YES
Load: 70%
Lines of code: 106 + ProcessingJS (800K)
It is drawn in the ProcessingJS environment at 800K of uncompressed code creating a language like Rapier. A snowman is drawn with the same code. An example is a special one. It shows that you can do anything with shells (for solving simple problems in complex ways), and even in this case, Canvas does not catastrophically lose to DOM solutions.
Article (en) , 2012Code: GithubDemo: Full Screen
Particles per demo: 500
Type: Canvas
Sandbox? Not
Load: 100%
Lines of code: 50 + 100 in * .html + ThreeCanvasJS (72K)
72K compressed unpacked code from ThreeCanvas.js library. 3D scene with the rotation of its mouse movement. Here, for the sake of smooth movement, a low bitrate is set, therefore everything is beautiful, but as a background action it is not too suitable.
Year: 2010Code: JSDemo and description: full screen
Particles per demo: 60 , spin in the plane of the picture
Type: Canvas
Sandbox? Not
Load: 100%
Lines of code: 160
Very frequent animation does not allow us to appreciate the advantages of Canvas. There is a rotation of drawn snowflakes around its axis, a slow fall with wanderings. But some of them “walk” along sinusoids, torsion in one plane does not at all give realism, which, on the contrary, rejects the perception of the effect, and creates, rather, an importunity effect. Code - on the contrary, shows its power and compactness. In sum - excellent efforts are aimed at achieving a bit of the wrong effects that for the consumer are no better than energy-consuming DOM engines.
 
  Let's look at examples of scripts that work with DOM (layers), without Canvas.

Year: 2009Demo: jSnow - jQuery Snow Effect , full screenCode: JS (uncompressed legacy)
Particles per demo: 25
Type: DOM
Sandbox? Not
Load: 70%
Lines of code: 160 + jQuery
Options in the Fiddle sandboxes (symbolic snowflakes are used everywhere):
  • Packed (obfuscated) original code in the sandbox with adaptation to jQuery 2.
  • Unpacked, but poorly moving (small sine waves) mod mod1 code in the sandbox with adaptation to jQuery 2.
  • Restored with refactoring of names, style, the most similar and working code (Fiddle) of this script in the sandbox. Stops / starts by the stop button. In compressed form - 1.5K.
  • Extended to the ability to run multiple objects in blocks or in the whole window. Running through the collection. In compressed form - 1.8 K, less than the original, which is 2.2-2.4 for different mods.
This script has a characteristic handwriting of particle movements (strongly to the sides). If you look closely, these are just very large sinusoids, perceived as one large whirlwind in the middle of the window. He is very restrained in wasting resources. Source code version 1.2 - lost or always been obfuscated by the packer; unpacked versions 1.1.mod2 (modified by other authors) - are in the Codepen sandbox, but do not work with new jQuery, because they refer to canceled $ .browser. And they show signs of unpacking. Looks great in low headers ( example ), when the sine waves do not have time to overlook. Of the dozens of examples, if you look closely at a couple of them (in execution and code), then this example is one of them. Therefore, we will take up the jSnow version thoroughly by running it in the sandbox.
Interestingly, the packaged version of the author, 1.1 or 1.2, is much faster - with the same external settings it loads the processor by 40% , and 1.1.mod2 - by 55% . (Fiddle also doesn’t work faster in multi-window mode.) Most likely, unnecessary checks affect the snowflake rendering cycle (“features” have been added to the mods). The code itself is not very optimized - it writes inline styles that can be set by rules.

Then it became more interesting - a number of bugs were found in the code with the tested settings (and this does not mean that all were found). You will have to make some changes in the code (remove incompatibility with jQ 2+, calculate the initial position of the snowflake, prevent them from going beyond the left edge of the window - in poppies this leads to a “flashing” of the scroll bar, and it’s useful to do the same for the lower border ), so use the better modified modern versions.

Mods (2009-2010) added a couple of important “features” - settings for the smooth disappearance of snowflakes at the bottom (fadeAway: 1) and the ability to scroll without moving the field of snowflakes (followScroll: 1). The names are left original, as their developers called.

The goal of debugging old code is to transfer the algorithm to Canvas and compare the speeds.(Cripple to win - not enough honor.) In the settings, I repeat the same mistakes that I criticized others over. It doesn’t matter for the developer that multi-colored snow falling in 2D does not happen - most importantly, there is a technical opportunity to colorize. And yet, not snowflakes are flying, but lumps in reality. But 3/4 of the Earth’s population does not know this, so success awaits us ... In the set of snowflakes, most Unicode characters, similar to snowflakes, were used - as many as 8. You can find as many more.

So, it turned out a readable code, 20 lines shorter (90 lines) and packaged 30% less (1.5K) than the best mods without losing functions and adding a stop-start button. This intermediate version is compact, but it works, as before, with a window and can absolutely set the height (height: number) in the parameters. This is not very convenient, especially since the plugin does not use a contextual collection at all, therefore it feels fine with a strange look of $ (). JSnow (...), i.e. without context. It turned out quite simply, we will limit ourselves here to a link to a demo .

And let's complicate the task - to start working with jQuery contextual collections. We will save this behavior when there is no context - we select the work with the window, as in the context of the window and $ ('body')) and add work with the container block (for example, run on $ ('. ContSnow'). JSnow (.. .)). The container will have to be prepared, it needs position: relative, so that the inserted block with absolute feels good. The block, which will behave differently over the whole window, will cover the window, so all the content of the page will need to be raised if there is such a block. (It’s possible otherwise, as before, but why complicate it? Rather, they will use either the first script or the second.) It will turn out something like this:

demo
, (code in repo) . This is the DOM, the load is 30% on the stream (15% is the total) with a bitrate of 12. It is
somewhat affected by the fact that the pictures are large and transparent.


In fact, why work with only one container if jQuery can provide a collection? It turns out something like this , a load of 30-50% for an amount of 70-120 particles. Stop-start can also be divided into buttons or shared.

When trying to apply what was written, it immediately catches the eye the impracticality of running a script on a collection. Run - yes, you can even dozens of instances of scripts, distributing to each a little bit of snowflakes. But the same parameters are reported to all blocks of the collection, and this is impractical, because more often I want to do another task - to launch a few windows (virtual, on divas), but with different parameters, and for this we have to communicate them to one element. It turns out, most often, that how many elements, so many .jSnow launches are needed, which turns out to be long, although clearly.

There is an analogy with writing CSS rules. Rules are the same declarations of parameters that we do when we run plugins, even selectors for plugins are in place. But now there is no way for mechanisms to gradually accumulate descriptions of rules (similar to font-size in one and position in the other). The second launch of the plugin on the same element adds another instance of the plugin (long-running function with a closure and the ability to shut down), and does not add properties to the already running one. In this case, it would be more convenient to list selectors (just strings with classes) rather than JSON settings. But I will not recall a single plugin where such a way of constructing settings would be needed and worked. In the most advanced version of the demo, we will write a launch in 4 areas, just as the plugin can now:


demo
, (cat in repo) , loading 50% at 75 particles and 12 FPS.


Improvements to the plugin added about 300 bytes of compressed code, but now it can be called a plugin with more reason. True, without a single method.

Other scripts for working with the DOM


Such attention is paid to one script, not the most advanced one, because if you look ahead, it turns out to be a little competitor to Canvas scripts, not the one that is higher, but well written economically. Ineffectively written ones will not become competitors, therefore nothing superfluous can be allowed in the code so that there is something to compare with.

For example, there is a very popular DOM script called Snowstorm , with a compressed code of 20K, a very large number of settings, disabling in mobile devices - there is something to learn for small scripts. But to study what is superfluous and whether it leads to losses is too difficult a task. It’s easier to write small and expand settings. The significance of each will be revealed through tests and practice.

Let's quickly go through another small script that is not found among well-designed demos and sandboxes, but has interesting behavior (mentioned above, by P. Gehrig). There is no big difficulty putting it in the sandbox - it doesn’t require any improvements, jQuery doesn’t use it, but it took you to get used to modern doctype. Also, it used to be bad with special Unicode characters in system fonts, now it’s better, so the falling letters are replaced with falling textual (highlighted) snowflakes.
Year: 2005, falling-snow with settings , code , jsFiddle
Particles per demo: 25
Type: DOM
Sandbox? YES
Load: 10% (due to 8 FPS)
Lines of code: 90
Such a small system load in the original script settings is caused by the low FPS set. This, of course, is noticeable in movements as a frequent slideshow. This was needed for older browsers and is warned in old script comments. At 30 FPS, the load is 35%, about the same as the previous script with the same settings.

This script has a modification with the addition of Brownian motion and with the fall of the “from a distance” of the screen, increase and “melt” (increase transparency) near or below.
Year: 2006, falling-snow with falling “from afar” with settings , jsFiddle
Particles per demo: 25
(watch in full screen)
Type: DOM
Sandbox? YES
Download to jsFiddle: 60% (16 FPS)
Lines of code: 100
Here, the size settings are quite “capricious” - with a small change in the growth rate you can get huge snowflakes or not growing, so you need to select other behavioral scenarios, and the effectiveness will ultimately depend on the size of the window and behavior (not auto-adjust). A noticeable increase in load is associated with the rendering of large transparent characters (images). (The source code is written tight, the actual amount of code after thinning would be 2 times more.)

We will write all the code options with snow on Github. We will take into account the flaws of the predecessors who did not write demo pages, and therefore much less people looked at their code. Github makes it extremely easy to run a demo if you work in the gh-pages branch. Now all version modifications are easily recorded in the change history and the differences are seen. Github: github.com/spmbt/snowfalls .

What about CSS animations?


We look at examples written by others, further, in search of effective algorithms and spectacular results.

1. An example (almost the only one with CSS animations ) of heavily loading CSS3 animations with DOM snowflakes rotation - www.jqueryscript.net/animation/jQuery-Plugin-For-Snowfall-Effect-with-Rotating-Snowflakes.html . (This site has everything - description, code and demo for each script, but without sandboxes.)

2. Animation on 3 picture layers in CSS (Codepen).

We try to watch more animations on the canvas to find a script that does not load the system too much.

An example of animation on Canvas, activated by mouse movement, where you can see that the acceptable number of snowflakes is not continuous generation from about 200-300, but about 50-100 on the screen - www.jqueryscript.net/animation/Yet-Another-Falling- Snow-Animation-with-jQuery-Canvas-GlauserChristmas.html .

Another animation on Canvas without libraries, with a demo and comments in Chinese: www.jqueryscript.net/animation/Nice-Snow-Falling-Effect-with-jQuery-Canvas-Nice-Snowing.html .

For some reason, all these animations, including Canvas, are set up so that they load the processor 100% (more precisely, one core that single-threaded JS can load). This seems to be considered normal for script demonstrations. (Perhaps this is true on discrete graphics cards.)

Somehow it's all weird


Among the scripts with snow, there are very few CPU-saving loads, although they are available for both the DOM and Canvas. We show that the same full load effect can be achieved not for 100, but for a couple of thousand snowflakes, and it is better to consider normal kernel loading by 10-20% for 200-400 pieces.

Choosing an Effective Canvas


However, there was one economical script on a clean Canvas. We will do our own examples approximately in his style.
Year: 2015Demo: Snow Effect using HTML5 Canvas and Javascript , Full ScreenCopy on jsFiddle
Particles per demo: 25
Type: Canvas
Sandbox - YES
Load: 45%
Lines of code: 90
The example shows that if we control all the code that does nothing more, as it happens in the examples above, then success is close. The load even with 200 particles (in Chrome) is 45% (you need to watch 2 or 3 processes - Chrome and two Chrome helper) and 60% at 2000. For Firefox - about the same, except that it is 10% slower (under good conditions) and more random inhibitory factors.
But Canvas is problematic at low loads. The load at 2 particles is often 40-60% and the same for 25, and 0 for the non-running setInterval (). Any drafting of it loads the processor (at 30 FPS - percent of 30), and the amount of drafting does not matter much. Obviously, with a worse graphics card, the results will be worse, and somewhere we will stop seeing improvements, it will always start to slow down if there is a Canvas, and correction can only be done by decreasing FPS.

In more detail, the results are as follows. We take jsFiddle as less affecting the results, copy the example there with the additionstop buttons. We start a different number of snowflakes, wait about a minute, until the processor's expenses calm down (without moving the mouse, doing nothing). We watch the results through Activity Monitor (MacBook with Intel HD Graphics 5000 video). If you look at Windows, say, on a 4-core processor, you will see a load of no more than 25%. 100% referred to here in the article are related to loading one core , i.e. 25% will need to be multiplied by 4. Just browsers do not know how to parallelize in a different way, but this load on the laptop is quite sensitive, leads to energy consumption, approximately as when watching a video.

Unfinished rendering -10% load (background).
0 particles - 30%;
2 parts - 35%;
25 particles - 40%;
200 particles - 50%;
1000 - 55%;
2000 - 65%.
In this case, the readings are not always repeated, it depends on other running programs and memory usage.

That’s the answer to why, with the advent of Canvas, everyone didn’t immediately rush to program on it. The processors, the initial possible imperfection of the implementation and incomplete support in browsers did not allow us to make an acceptable bit rate so that with a good quality of movement we could pass the “performance qualification”, which depends not on the number of particles, but on the bitrate, and at the same time keep within the ideal of 20%. With animation on layers, you can run at least 5 particles and pass this qualification. Now it’s better with performance, and IE8, which without Canvas, takes about 0.5 percent .

Custom Canvas Algorithms


Let's create our own variants of economical algorithms on canvas. First, we close the plane into the torus and let the snowflakes go downwind with small random walks that apply to the speed of each particle. It turns out quite naturally, although without the impression of gusts of wind. The second effect is parallax, when smaller particles fall more slowly, which creates a feeling of three-dimensionality of the scene.

With such settings, the first pancake went.
Year: 2015Demo and sandbox: wind with a fall and random wanderings of speed , the whole screen wrapped in a torus
Particles per Demo: 100
Type: Canvas
Sandbox - YES
Load: 35%
Lines of code: 50
The randomness of the walk leads to the fact that some particles, a rather large number of them, fly, gradually changing direction and fly more and more randomly. It is necessary to “attenuate” the velocity deviations so that a swarm of particles is reduced to a common flow. The * .999 factor in the code creates this “reassurance”. But it affects speed in general, so over time they will slow down more and more. For an endless fall, this is not suitable, but you need a fall within the screen.

The next step is the creation of the earth. The snow will stop on it and melt, so that, when melted, the particles appear again from above (for simplicity, there will still be the same number of particles, without optimizations).
Demo 2 and the sandbox: Scene with melting snow at the bottom of the window , full screen
Particles per demo: 1000
Type: Canvas
Sandbox - YES
Load: 40-50% (30 FPS)
Lines of code: 50
The size of the particles affects where they will stop: the larger the particle, the closer to the bottom of the window. This also creates the effect of three-dimensionality and the random filling of the “earth” with snowflakes.

First, you need to launch a snow charge more powerful, so that a cover quickly forms. After a minute, it will begin to melt before our eyes, and the completely melted particles in the bottom go up. The water cycle.

For an initially equilibrium process, of course, you need to evenly deliver snow from heaven. But the seasons of melting and snow charges have their own charm and dullness. From this demo we immediately get a picture with deers , the link to which was at the top of the article ( code in the sandbox , 30% load, 120 particles).


Kafeman Hackathon Scripts


In parallel, kafeman made scripts with snow and other holiday effects .
The initial idea is to build a welcome page with effects for ADM club visitors. Everything could be more serious , but history does not tolerate the subjunctive mood. In addition to a purely decorative design, I visited the idea of ​​looking at real snowfall ( 1 , 2 , 3 ) and simulating those unpleasant closely flickering particles of snow. Perfection has not yet been achieved , but the direction has every reason, otherwise the distracting snow sculpted on the face will not be remembered. Here you need to experiment with rendering shapeless flakes and their blurry flickering.

And you need to somehow grow the snow cover: jsfiddle.net/162e4jte/3 , but not so that it swallows the entire planet with an astronaut on it. At first, he also lay down as tubercles and melted: jsfiddle.net/162e4jte/1 . This behavior was found in scripts of other authors.

Well, for the future, the idea of ​​combining engine generators into one also deserves execution. According to the results, in addition to the mass of scripts of third-party authors, we have 3-4 particle motion algorithms and 2 implementation methods, the common parts of which are pretty good in the submitted sandboxes and repos are tracked.

Some statistics. Due to global warming, interest in snow in conjunction with Javascript , as well as skiing, is falling, and interest in Canvas and Javascript- is growing. Now we know in which combination stable interest will be ensured.

Conclusion


The two programming methods that are really feasible for the snow effect - DOM layers and Canvas - have their own application niches. Up to about 50 particles, the DOM wins, but not in all modes, for tasks where a small load on the processor is needed. High bitrate lowers the bar. More than 50 (but confidently - more than 200) - but also with a preferably low bitrate - Canvas wins. But you need to fork out for more downloads - from 30% of the processor resources. Border and criteria are very unstable and depends on the hardware, browser, success of the engine implementations in browsers. A mobile user will say categorically “no” to more than 5 particles, and a stationary with a large video card will not sincerely understand what the problems are with 200 particles in the DOM and with 5000 in the Canvas.

All that is superfluous from the algorithm for a typical commercial application (user attention in the holiday area) needs to be removed, algorithms tested on different devices and decisions about the niche of user coverage are necessary. There may be a more winning low-bit illumination on Canvas or short-term fireworks on it. It does not hurt to tell which button to turn off the animation and remember in the user’s settings that “the action worked out”. Since the snow is not as monetary as the Yandex browser, there is no reason to “break” this button consciously. In a couple of years, we can hope that the situation with the canvas will improve, and he will slowly select for himself an area of ​​a small number of particles and an increased bitrate.

The expressive possibilities of the snow scripts are basically exhausted at this stage (nothing qualitatively new has appeared in recent years in this group). Enoughly completed scripts have a number of properties recognized as necessary, and some performance-impractical properties (rotation of snowflakes in 3D format) are not performed, but this does not bother anyone. But due to productive rendering on canvas, one can expect that such scripts will appear (with a load of 30%).

Perspectives of coding - you can write constructors that would give an object for the DOM or Canvas by settings. Designers could write different authors. With this approach, a project was organized at HabraADMe (Github): github.com/clubadm/snowmachine . Running current code from this repo via jsFiddle .

Only registered users can participate in the survey. Please come in.

How do you feel about the appearance of falling snow animations on the pages of websites?

  • 33.3% Always negative, if there is no alternative not to look at such a page 82
  • 44.3% More often negative, but with unobtrusive effects - neutral or positive 109
  • 7.3% Neutral, I do not notice such animation effects 18
  • 19.5% More often positive, but sometimes there is a desire to turn off 48
  • 4.8% Always positive, almost no cases of excessive animation 12

Also popular now: