First, you need a basic knowledge of queues (queue). See the previous chapter.
Related tutorials: A summary of the animation process under jquery: http://www.jb51.net/article/42000.htm
JQuery 1.9.1 Source Analysis Series (15) animation processing of the slow motion animation core tween:http://www.jb51.net/article/75821.htm
A. Animation entry jQuery.fn.animate function execution flow detailed
--------------------------------------------------------------------------------
First, the parameters are called Jquery.speed to obtain an animation-related parameter, and an object similar to the following is generated. and generate animation execution function doanimation
Optall = {
complete:fnction () {...},//animation execution-Complete callback
duration:400,//animation execution length
easing: "Swing",//animation effect
queue : "FX",//Animation queue
old:false/fnction () {...},
}
var empty = Jquery.isemptyobject (prop),
Optall = Jquery.speed (speed, easing, callback),
doanimation = function () {
//operate on a copy of feature to ensure that each feature effect is not lost
var anim = Animation (This, Jquery.extend ({}, prop), optall);
Doanimation.finish = function () {
anim.stop (true);
Empty animations or finishes need to be immediately resolved
if (empty | | Jquery._data (this, finish)) {
anim.stop (true);
}
;
If no animation is executing, animate immediately, otherwise press the animation into the animation queue for execution
No animation executes immediately, or the animation is pressed into the animation queue waiting to execute return
Empty | | optall.queue = = false?
This.each (doanimation):
As you can see, the place where the animation is actually performed is animation (this, Jquery.extend ({}, prop), Optall) function
B. jquery internal functions Animation detailed
--------------------------------------------------------------------------------
Animation (Elem, properties, options). Properties is the CSS feature that you want to animate, options is the animation-related option {complete:function () {...},duration:400,easing:undefined,old:false,queue: "FX "}。
First, a delay object is initialized, which is used to process the animation queue.
deferred = Jquery.deferred (). Always (function () {
//don ' t match elem in the:animated selector
Delete Tick.elem;
Then, a function tick, which is executed at each point in time (the event interval of two adjacent points is 13 milliseconds by default), is stored in the jquery.timers and is then taken out every time the JQuery.fx.tick is executed.
tick = function () {
if (stopped) {return
false;
}
var currenttime = Fxnow | | Createfxnow (),
remaining = Math.max (0, Animation.starttime + animation.duration-currenttime),
//Archaic CRAs H Bug won ' t allow us to use 1-(0.5 | | 0) (#12497)
temp = remaining/animation.duration | 0,
percent = 1-te MP,
index = 0,
length = animation.tweens.length;
Performs animation effects for
(; index < length; index++) {
animation.tweens[index].run (percent);
}
Generate progress Reports
Deferred.notifywith (Elem, [animation, percent, remaining]);
If (Percent < 1 && length) {return
remaining;
} else {
//animation completed, perform all functions in the deferred queue (including purging animation-related data)
deferred.resolvewith (Elem, [animation]);
return false;
}
We see jquery's handling of animation progress:
Percent of progress = 1-percent of time remaining.
Normally we do this: Suppose the time is 13 milliseconds to perform an animation, the current is nth this execution, the total animation length of T. So
Percent of progress = (n*13)/T
In fact, the time n*13 of this algorithm is not accurate, because the CPU is not only a program in your execution, time slices to you are often larger than the n*13. And it's a very inaccurate value, causing the animation to feel fast and slow and incoherent. jquery, in this way, guarantees the accuracy of animation execution at the current event point, after all, the event is the latest calculation.
Third, generate animation with all the characteristics of the object animation (this object structure as shown in the source code), Animation.props saved in the user's incoming characteristics (animation final goal).
Animation = Deferred.promise ({elem:elem, props:jQuery.extend ({}, properties), Opts:jQuery.extend (true, {SPE Cialeasing: {}}, Options), Originalproperties:properties, originaloptions:options, Starttime:fxnow | | Createfxnow (), Duration:options.duration, tweens: [], createtween:function (prop, end) {var tween = jquery.t
Ween (Elem, animation.opts, prop, end, animation.opts.specialeasing[prop] | | animation.opts.easing);
Animation.tweens.push (tween);
return tween; }, Stop:function (gotoend) {var index = 0,//If we are going to the "end", we want to run all tweens/ /Otherwise we skip this part length = Gotoend?
animation.tweens.length:0;
if (Stopped) {return this;
} stopped = true;
for (; index < length; index++) {animation.tweens[index].run (1); }//Resolve when we played the last frame//otherwise, reject if (gotoend) {Deferred.resolvewiTh (Elem, [animation, Gotoend]);
else {deferred.rejectwith (elem, [animation, Gotoend]);
return to this; }
})
Finally, call Propfilter to modify the CSS feature name so that it can be identified by the browser, which should be noted that Borderwidth/padding/margin refers to not a CSS feature, but four (up and down)
After Propfilter,animation.opts.specialeasing added the corresponding features
An example is provided to illustrate the Propfilter correction results.
The modified result of the example 1,css feature {height:200} is:
The modified result of the example 2:,css feature {margin:200} is:
Props = {marginbottom:200,marginleft:200,marginright:200,margintop:200}
Five, call Defaultprefilter to do the adaptation processing: for instance the Height/width animation request display and overflow for the specific value to have the effect; for example, the Show/hide animation needs to animate a lot of CSS eigenvalues, and call Createtweens to generate the ease animation in the function.
Animationprefilters[0] = Defaultprefilter for
(; index < length; index++) {Result
= animationprefilters[ Index].call (animation, Elem, props, animation.opts);
if (result) {return result
;
}
where animationprefilters[index] worthwhile function is defaultprefilter,defaultprefilter function processing there are several more important places
Defaultprefilter Key 1: height/width related animations in inline elements need to set the display feature value to Inline-block
Height/width Overflow Pass
if (Elem.nodetype = 1 && ("height" in props | | "width" in props) {//
Make sure nothing sneaks out
//record 3 overflow related features, because IE cannot change overflow eigenvalue,
// When Overflowx and Overflowy set the same value
Opts.overflow = [Style.overflow, style.overflowx, style.overflowy];
Height/width related animations in inline elements need to set the display feature value to Inline-block
if (jquery.css (Elem, "display") = = "inline" &&
Jquery.css (Elem, "float") = = "None") {
//inline element accept Inline-block;
Block-level elements must be embedded in the layout
if (!jquery.support.inlineblockneedslayout | | css_defaultdisplay (elem.nodename) = = "inline") { C12/>style.display = "Inline-block";
} else {
style.zoom = 1;
}
}
Defaultprefilter Focus 2: For Height/width animation overflow to be set to "hidden", the animation is completed after recovery. This helps to improve rendering speed.
For Height/width animation overflow to be set to "hidden", the animation is completed after the recovery
if (opts.overflow) {
Style.overflow = "hidden";
Shrink wrapper block
if (!jquery.support.shrinkwrapblocks) {
anim.always (function () {
Style.overflow = Opts.overflow [0];
STYLE.OVERFLOWX = opts.overflow[1];
Style.overflowy = opts.overflow[2];}
Defaultprefilter key 3:show/hide Animation special handling: Show/hide animation call GenFX get shape like
Props = {
Height: "Hide"
marginbottom: "Hide"
marginleft: "Hide"
marginright: "
Hide" MarginTop: "Hide"
opacity: "Hide"
paddingbottom: "Hide"
paddingleft: "Hide"
paddingright: "Hide "
paddingtop:" Hide "
width:" Hide "
The features that need to be animated are pressed into the handled list and the corresponding feature is deleted, followed by a corresponding easing animation.
For (index in props) {value = props[index]; Rfxtypes =/^ (?: toggle|show|hide) $/.
You can see that the only and show/hide animations will be Raujou handled if (rfxtypes.exec (value)) {delete props[index]; Toggle = Toggle | |
Value = = = "Toggle"; If the state of the current node is the same as the specified state, it does not need to be processed directly to the next state judge if (value = = = hidden?
"Hide": "Show")) {continue;
} handled.push (index);
}///There is a need to perform the animation process into the branch, which will animate each feature animation length = Handled.length;
if (length) {datashow = Jquery._data (Elem, "Fxshow") | | jquery._data (elem, "Fxshow", {});
if ("hidden" in datashow) {hidden = Datashow.hidden;
//Toggle need to save state-enables. Stop (). Toggle () to "reverse" if (toggle) {Datashow.hidden =!hidden;
} if (hidden) {jQuery (Elem). Show ();
else {Anim.done (function () {jQuery (elem). Hide ();
});
} anim.done (function () {VAR prop;
Jquery._removedata (Elem, "fxshow");
For (prop in orig) {Jquery.style (Elem, prop, orig[prop]); }
});
for (index = 0; index < length; index++) {prop = handled[index];
Generate a slow motion animation tween = Anim.createtween (prop, Hidden datashow[prop]: 0); orig[prop] = datashow[Prop] | |
Jquery.style (Elem, prop);
if (! (prop in datashow)) {datashow[prop] = Tween.start;
if (hidden) {tween.end = Tween.start; Tween.start = Prop = = "width" | | Prop = = "Height"?
1:0; }
}
}
}
VI, to generate the ease of animation, show/hide in the Defaultprefilter function has been processed (above the source code).
Let's take a look at what the Createtweens has done, first look at the animation object before Createtweens
Then look at the tweens array of animation objects after createtweens into a
The margin is decomposed into four properties (Margintop/right/bottom/left) and each property has its own animated feature.
Seven, start the animation timing, timed execution tick
Start Animation timing
JQuery.fx.timer (
jquery.extend (tick, {
Elem:elem,
anim:animation,
queue: Animation.opts.queue
})
Finally, the incoming animation end callback is added to the deferred queue
Get the callback function from options add to the delay queue return
animation.progress (animation.opts.progress)
. Done (Animation.opts.done, Animation.opts.complete)
. Fail (animation.opts.fail)
The animation function process ends here.
Expand:
The GenFX function mentioned earlier is specifically used to obtain the relevant features of the animation required for toggle, hide, and show.
The resulting attrs = {
height: "Show",
margintop: ' Show ',
marginright: ' Show ',///when Includewidth is False
MarginBottom: "Show",
marginleft: "Show",///when Includewidth is false without
opacity: "Show",
width: "Show"
}
function GenFX (type, includewidth) {
var which,
attrs = {Height:type},
i = 0;
If the width is included, the step value is one to complete all cssexpand values,
//If the width is not included, the step value is 2 skipped left/right value
//cssexpand = ["Top", "R", "Bottom", "left"]
includewidth = includewidth 1:0;
for (; i < 4; i + = 2-includewidth) {
which = cssexpand[i];
attrs["margin" + which] = attrs["padding" + which] = type;
}
if (includewidth) {
attrs.opacity = Attrs.width = type;
}
return attrs;
Animation function is more complicated, children's shoes can use the example to trace the code casually. This is a better way to understand the jquery source code. Two examples are recommended:
First, there are hide/show examples: $ ("#id"). Hide (1000);
Second, other examples: $ ("#id"). Animate ({"marginleft": 500},1000);
JQuery 1.9.1 Source Analysis Series (15) animation processing of all the content to introduce to you here, have a problem at any time to give me a message, thank you.