📜 ⬆️ ⬇️

Animated javascript banners are just *

*) In fact, it is still difficult, but simpler than before.

The story began with the formulation of the problem: you need to make an animated banner with about thirty objects using HTML + javascript in one day. The day, of course, the banner was not made, and was made for two efforts of three man-days. After the assignment, the library of batch animation remained, which I called Scenario . I want to tell about its modified version.

The main idea of ​​the library is to collect information about all animated objects in one script and send it for execution. One script can be executed as many times as desired or it can be modified, since it is the usual Javascript structure.

Running a script from anywhere is extremely simple:
')
var newScenario = [...]; $.scenario(newScenario, { complete: function(time) { alert('!'); } }); 

It remains only to figure out what to write instead of the three points in the example :)

Script Description


Any script is an array of animated objects or a single animated object. Each animated object can contain three basic properties:
Thus, the whole script is a tree of animated objects. Moreover, the structure of this tree is not obliged to coincide with the structure of HTML elements, the animation of which is described by the script. It seems to me that starting the script is most convenient with building this tree. In the end you should get something like this:

 var newScenario = { element: '#scenario', child: [{ element: '.rocket_smile' child: [{ element: '.fire' }, { element: '.eyes' }, { element: '.ears' }] }, { element: '.rocket_atack' child: { element: '.fire' } }, { element: '.cloud', child: [{ element: ['eq', 0] }, { element: ['eq', 1] } }] }; 


And now the magic is the description of the scene object.
The parameters before and after allow in most cases to do without the callback functions start and end. In addition to the usual css-properties, you can specify some additional manipulations over the elements being animated: the functions show, hide, attr, removeAttr, addClass, removeClass, toggleClass are supported. A small example from which everything will become clear:

 scene: [{ time: [2500, 4000], before: { opacity: 0, show: '' }, animate: { opacity: 1 } after: { opacity: '' } }, { time: [5500, 6500], before: { addClass: 'rocket_wink' }, after: { removeClass: 'rocket_wink' } }] 


Well, the spherical code of clouds in a vacuum:

 { element: '.cloud', child: [{ element: ['eq', 0], time: [0, 7500, 'linear'], before: { top: -80, display: 'block', left: 300 }, animate: { top: 374 } }, { element: ['eq', 1], scene: [{ time: [2500, 5500, 'linear'], before: { top: -80, display: 'block', left: 500 }, animate: { top: 374 } }, { time: [5500, 9000, 'linear'], before: { top: -80, display: 'block', left: 150 }, animate: { top: 374 } }] }] } 


Note that the .cloud element has no animation at all, and the eq (0) element does not contain the scene property, but contains the time, before and animate properties - this is an opportunity to shorten the script a little more.

For mastering the basic principles is enough.

Why not do everything on jQuery.animate. Living example


I will answer the second part of the subtitle. I have prepared an example of animation made with the help of Scenario. The example is very similar to the banner, which was discussed at the very beginning, although I cut out all the identity from it and replaced the main characters with a ninja. In addition, for the sake of interest, I made the same banner on jQuery.animate (the one below).

Living example

And this is why jQuery.animate is not very suitable for such tasks:
  1. Animate calls the complete function after the animation ends. But she does not cause anything before the start. Because of this feature, you have to use queues:
     .delay(2500) .queue(function(next) { $(this).css({top: 82, left: 74}); next(); }) .animate({top: 85}, 1500) 

  2. Animate animates all HTML elements in the current jQuery object independently of each other. For each of the elements after the end of the animation, the complete function is called. The step function is called for each property of each element at each animation step. This is even more uncomfortable.

  3. Through animate, you can not just run the step function for a certain time. When empty set of animated properties animate returns immediately the result. We have to use a dirty trick: animate any value from 0 to 0.

  4. Many exit points of the animation. If 10 different objects finish the animation at the same time, what’s the complete event of which one to put the final banner code? Which complete event should look for this code in 10 days?
    Scenario, by contrast, has one exit point, this is the complete $ .scenario () function
Because of these problems, the following code is obtained:

 //    ,      var $rocket_smile_fire = $rocket_smile.find('.fire'); $rocket_smile_fire //  :  ,       .eq(0) //  : marginTop   0,        .animate({marginTop: 0}, { duration: 9000, step: function(x, opt) { //    this,     $rocket_smile_fire .hide() //          .eq(((new Date() - opt.startTime) / 100) % $rocket_smile_fire.length) .show(); }, complete: function() { $rocket_smile_fire.removeAttr('style'); } }); 


This, of course, sad, but you can live, if not ...

Killer feature Scenario


Imagine: the animation you do lasts 20 seconds. You make the final scene that lasts two seconds. How much time is wasted while you are viewing the banner until the last seconds? How to solve a problem in jQuery? Comment out the piece of code that does most of the work. It’s not a fact that all the objects will be in their places, because the code that moved them is commented out.

The decision from Scenario - just specify from what time to start the scene and in which to finish. Well, the playback speed can be set. And the frame rate to the heap.

An example with the ability to adjust the time

Debugging is a pleasure.

More about scripts


Without a description, the property of the element object being animated and the callback function for the scenes remain. Fill the gap. Element can have the following values:

The start, end, and step callback functions are executed in the context of the found element. The first argument all three take the time elapsed from the beginning of the script. Last of all is the current scene object, expanded by the animation object:

 { element: '.rocket_smile', button: $('#start-button'), scene: { time: [0, 2500], fadeDuration: 400, start: function(time, scene) { // scene.fadeDuration     // scene.button     scene.button.fadeOut(scene.fadeDuration); }, animate: { top: 69 } }, } 


The step callback function, in addition to these two parameters, accepts another parameter with detailed information about the current animation step:
- time , time from the beginning of the script;
- passed , time from the beginning of the scene;
- progress , time from the beginning of the scene, normalized over the segment 0..1;
- position , this is progress after applying the ising function.

 { element: '.rocket_atack', scene: { before: { top: 20 }, //  ,    step lastTop: 300, step: function(time, opt, scene) { //    var startTop = scene.before.top; //     var changeTop = scene.lastTop - startTop; // this —   this.css({top: startTop + changeTop * opt.position}); } } } 


Scenario Code on Github


Future plans

Many did not understand that the visual editor is a joke. I write in plain text - this is a joke.

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


All Articles