Move----to write a JS library with several common animations

Source: Internet
Author: User
Tags jquery library

While manipulating the DOM elements to make the site more vibrant or something to be noticed, there are often small animations that need to be used, but the usual jquery library has only one ease (the animation that accelerates and slows down first), although this is a very popular animation, but sometimes it uses other, Recently wrote a library integrating several commonly used animations, move.js, if not the animation queue, the usual animation library in an animation, when the element is applied to another animation will immediately stop the current animation, immediately execute the newly added animation, move animation library slightly modified, after the new animation added , the old animation will continue to run, and two animations will be superimposed. You can click Start in the demo demo, the demo demo

Four Common animations:

    • Ease----accelerated after the acceleration of the animation, the initial speed of small start to accelerate, over the midpoint to slow down, which is also the jquery default animation
    • EaseOut----At the beginning of a large speed, has been doing deceleration movement
    • Collision----Collision animation, the initial speed is small or 0, has been accelerating, the impact of the end of the time rebound, like basketball landing
    • Elastic----Elastic animation, the initial speed is large, has been doing acceleration reduction accelerated motion, reached the end position acceleration of 0 (because the resistance is set, so the acceleration of 0 in the place before the end), swing back and forth

Animation curve:

With animation curve, these kinds of animation is actually a simple physics problem, only need to pay special attention to the end position pixel deviation how to deal with.

End position Processing

Because the timer used to do animation, the time interval is 13ms, because jquery is also 13ms, I tested 13MS can also get a relatively smooth effect, but because the browser refresh interval is 16.7ms, I understand that it is necessary to do more than 3ms dom rendering, this is not very certain,    Forget to know the friend pointing. Since the target value is close to several pixels per 13ms, if the timer is set to the target 1px at the end of the time, then the next time the target can be skipped, so the position is judged, if the speed is >0, and the current position has >= the target value, or the speed <0, The current position <= the target value, let the current position be in the target position.

The code is as follows:

var move = {css:function (obj, attr) {if (typeof attr = = = = "string") {return obj.currentstyle? obj.c        URRENTSTYLE[ATTR]: window.getComputedStyle (obj, false) [attr];            } else if (typeof attr = = = = "Object") {var A;                    For (A in attr) {switch (a) {case ' width ': case ' height ':                    Case ' left ': Case ' top ': Case ' right ': case ' padding ':                    Case ' paddingleft ': Case ' paddingright ': Case ' paddingtop ':                    Case ' paddingbottom ': Case ' margin ': Case ' marginleft ': Case ' marginright ': Case ' margintop ': Case ' marginbottom ': case "Borderradius": Case "BorderWidth": if (typeof attr[a] = = = "Number") obj.sty LE[a] = Attr[a] + ' px ';                        else obj.style[a] = Attr[a];                    Break                        Case "opacity": if (+attr[a] < 0) Attr[a] = 0;                        Obj.style.filter = "Alpha (opacity=" + attr[a]*100 + ")";                        obj.style.opacity = Attr[a];                    Break                Default:obj.style[a] = Attr[a];                }}}, Init:function (obj, JSON, time) {if (!obj.ani) {Obj.ani = {}; Animated Object obj.ani.s0 = {},//Current value Obj.ani.st = {},//target value obj.               Ani.dis = {},//target value and starting value distance Obj.ani.va = {},//average Speed OBJ.ANI.V = {},             Initial speed, current speed OBJ.ANI.A = {},//Acceleration OBJ.ANI.D = {}, displacement in//t time period            Obj.ani.res = {};     The result of the moment}   Obj.aniover = false; Obj.ani.time = Time | |        500;        Obj.ani.interval = 13;        Obj.ani.total = Math.ceil (obj.ani.time/obj.ani.interval);                    Total number of timers obj.ani.t = 0;        Current times//If the first animation has not finished the second time, the second JSON attribute is passed into Obj.ani.st (the first time)//and the target value of the previous animation is not affected by Var attr;        For (attr in JSON) obj.ani.st[attr] = parsefloat (json[attr], 10);        For (attr in Obj.ani.st) {obj.ani.s0[attr] = parsefloat (move.css (obj, attr), 10);            OBJ.ANI.ST[ATTR] = obj.ani.st[attr];            OBJ.ANI.DIS[ATTR] = obj.ani.st[attr]-obj.ani.s0[attr];            OBJ.ANI.VA[ATTR] = obj.ani.dis[attr]/obj.ani.total;        OBJ.ANI.D[ATTR] = 0;        }}, Ease:function (obj, JSON, time, FN) {if (Obj.aniover = = = False) clearinterval (Obj.ani.timer);        This.init (obj, JSON, time);        var attr, this = this; Since the initial speed, maximum speed, and acceleration of each animation are different, these three separate settings for (attr in obj.ani.st) {Obj.ani.v[attR] = 0.5*obj.ani.va[attr];        Assuming the maximum speed is 3 times times the average velocity, the initial velocity is 0.5 times times, therefore is 3-0.5 obj.ani.a[attr] = (3-0.5) *obj.ani.va[attr]/(0.5*obj.ani.total);            } Obj.ani.timer = SetInterval (function () {obj.ani.t++;                    For (attr in Obj.ani.st) {if (Math.Abs (obj.ani.d[attr]) < Math.Abs (OBJ.ANI.DIS[ATTR]/2)) {                    OBJ.ANI.V[ATTR] + = obj.ani.a[attr];                OBJ.ANI.D[ATTR] + = obj.ani.v[attr]; } else if (Math.Abs (obj.ani.d[attr]) >=math.abs (OBJ.ANI.DIS[ATTR]/2) && Math.Abs (obj.ani.d[attr])                    <=math.abs (Obj.ani.dis[attr])) {obj.ani.v[attr]-= obj.ani.a[attr];                OBJ.ANI.D[ATTR] + = obj.ani.v[attr];                } Obj.ani.res[attr] = Obj.ani.s0[attr] + obj.ani.d[attr]; if ((Obj.ani.v[attr] > 0 && obj.ani.res[attr] > obj.ani.st[attr]) | | (Obj.ani.v[attr] < 0 && Obj.ani.res[attr] < Obj.ani.st[attR])) obj.ani.res[attr] = obj.ani.st[attr];                    if (obj.ani.t > Obj.ani.total) {clearinterval (Obj.ani.timer);                    Obj.aniover = true;                Break            }} move.css (obj, obj.ani.res);                if (obj.aniover) {obj.ani.st = {};                Obj.ani.res = {};            if (typeof fn = = = = "function") fn.call (obj);    }}, Obj.ani.interval);        }, Easeout:function (obj, JSON, time, FN) {if (Obj.aniover = = = False) clearinterval (Obj.ani.timer);        This.init (obj, JSON, time);        var attr, this = this;            Because the initial speed of each animation, the maximum speed, the acceleration is different, so these three separate settings for (attr in Obj.ani.st) {obj.ani.v[attr] = 5*obj.ani.va[attr];        OBJ.ANI.A[ATTR] = -6*obj.ani.va[attr]/(0.5*obj.ani.total);            } Obj.ani.timer = SetInterval (function () {obj.ani.t++; For (attr in obj.ani.st) {obj.ani.v[attr] + = obj.ani.a[attr];                OBJ.ANI.D[ATTR] + = obj.ani.v[attr];                OBJ.ANI.RES[ATTR] = obj.ani.s0[attr] + obj.ani.d[attr]; if ((Obj.ani.v[attr] > 0 && obj.ani.res[attr] > obj.ani.st[attr]) | | (Obj.ani.v[attr] < 0 && obj.ani.res[attr] < obj.ani.st[attr]))                    {for (attr in obj.ani.res) obj.ani.res[attr] = obj.ani.st[attr];                    Clearinterval (Obj.ani.timer);                    Obj.aniover = true;                Break            }} move.css (obj, obj.ani.res);        if (obj.aniover && typeof fn = = = "function") fn.call (obj);    }, Obj.ani.interval);        }, Collision:function (obj, JSON, time, FN) {if (Obj.aniover = = = False) clearinterval (Obj.ani.timer);        This.init (obj, JSON, time);        var attr, this = this, temp; Since the initial speed, maximum speed, and acceleration of each animation are different, these three separate settings for (attr in Obj.ani.st) {obj.ani.v[attr] = 2*obj. ani.va[attr];        OBJ.ANI.A[ATTR] = 6*obj.ani.va[attr]/(0.5*obj.ani.total);            } Obj.ani.timer = SetInterval (function () {obj.ani.t++;  For (attr in Obj.ani.st) {Console.log (Obj.ani.st) if (obj.ani.d[attr] = = = Obj.ani.dis[attr]                ) obj.ani.v[attr]*=-0.5;                OBJ.ANI.V[ATTR] + = obj.ani.a[attr];                OBJ.ANI.V[ATTR] *= 0.999;                temp = obj.ani.dis[attr]-obj.ani.d[attr]; if (Temp*obj.ani.v[attr] > 0 && math.abs (temp) < Math.Abs (Obj.ani.v[attr])) {Obj.ani.d[a                TTR] + = temp;                } else{obj.ani.d[attr] + = obj.ani.v[attr];                } Obj.ani.res[attr] = Obj.ani.s0[attr] + obj.ani.d[attr];                     if (obj.ani.t > Obj.ani.total) {for (attr in obj.ani.res) obj.ani.res[attr] = obj.ani.st[attr];        Clearinterval (Obj.ani.timer);            Obj.aniover = true;                Break            }} move.css (obj, obj.ani.res);                if (obj.aniover) {obj.ani.st = {};                Obj.ani.res = {};            if (typeof fn = = = = "function") fn.call (obj);    }}, Obj.ani.interval);        }, Elastic:function (obj, JSON, FN) {if (Obj.aniover = = = False) clearinterval (Obj.ani.timer);        This.init (obj, JSON);        var attr, this = this, factor={};            Because the initial speed of each animation, the maximum speed, the acceleration is different, so these three separate settings for (attr in Obj.ani.st) {obj.ani.v[attr] = 0*obj.ani.va[attr];        FACTOR[ATTR] = 0.06;            } Obj.ani.timer = SetInterval (function () {obj.ani.t++;                For (attr in Obj.ani.st) {obj.ani.a[attr] = (obj.ani.dis[attr]-obj.ani.d[attr]) *factor[attr];                OBJ.ANI.V[ATTR] + = obj.ani.a[attr];            OBJ.ANI.V[ATTR] *= 0.8; OBJ.ANI.V[ATTR] = OBJ.ANI.V[attr] > 0?                Math.ceil (Obj.ani.v[attr]): Math.floor (obj.ani.v[attr]);                OBJ.ANI.D[ATTR] + = obj.ani.v[attr];                OBJ.ANI.RES[ATTR] = obj.ani.s0[attr] + obj.ani.d[attr];                    if (Math.Abs (obj.ani.v[attr]) <= 2 && math.abs (obj.ani.dis[attr]-obj.ani.d[attr]) <= 2) {                    FACTOR[ATTR] = 0;                    obj.ani.v[attr]=0;                OBJ.ANI.RES[ATTR] = obj.ani.st[attr]; } if (Obj.ani.t > Obj.ani.total) {for (attr in obj.ani.res) obj.ani.res[attr] =                    OBJ.ANI.ST[ATTR];                    Clearinterval (Obj.ani.timer);                    Obj.aniover = true;                Break            }} move.css (obj, obj.ani.res);                if (obj.aniover) {obj.ani.st = {};                Obj.ani.res = {};            if (typeof fn = = = = "function") fn.call (obj);    }}, Obj.ani.interval); }}

      

In order to pass the parameter less, I use the namespace to manage the library, if I want to call the collision animation, just do it:

Move.collision (obj, {left:500, top:300}, +, function () {alert ("animation Complete");});

Several other methods of animation call the same way, but note that elastic does not require incoming time

Why is an ANI object declared under obj?

Because the animation is not walking the queue, so when the animation is in progress if the new animation, before the animation will stop, such as setting left from 100px to 600px, in the process of moving right, if you immediately apply a top from the current value to 500px animation, if all parameters (initial speed, target value, Time, etc.) is placed in the function as a local variable, each time a new one is set, and the previous target value disappears, so these attributes are placed in the ANI object under the DOM node object for easy administration.

This animation library principle is very simple, there are problems or deficiencies in the place to welcome correct, source download: Move.js, demo demo

Move----to write a JS library with several common animations

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.