2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
9 Code licensed under the BSD License:
10 http://developer.yahoo.net/yui/license.txt
14 * The animation module provides allows effects to be added to HTMLElements.
16 * @requires yahoo, event, dom
21 * Base animation class that provides the interface for building animated effects.
22 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
24 * @namespace YAHOO.util
25 * @requires YAHOO.util.AnimMgr
26 * @requires YAHOO.util.Easing
27 * @requires YAHOO.util.Dom
28 * @requires YAHOO.util.Event
29 * @requires YAHOO.util.CustomEvent
31 * @param {String | HTMLElement} el Reference to the element that will be animated
32 * @param {Object} attributes The attribute(s) to be animated.
33 * Each attribute is an object with at minimum a "to" or "by" member defined.
34 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
35 * All attribute names use camelCase.
36 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
37 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
40 YAHOO
.util
.Anim = function(el
, attributes
, duration
, method
) {
42 YAHOO
.log('element required to create Anim instance', 'error', 'Anim');
44 this.init(el
, attributes
, duration
, method
);
47 YAHOO
.util
.Anim
.prototype = {
49 * Provides a readable name for the Anim instance.
53 toString: function() {
54 var el
= this.getEl();
55 var id
= el
.id
|| el
.tagName
|| el
;
56 return ("Anim " + id
);
59 patterns
: { // cached for performance
60 noNegatives
: /width|height|opacity|padding/i, // keep at zero or above
61 offsetAttribute
: /^((width|height)|(top|left))$/, // use offsetValue as default
62 defaultUnit
: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
63 offsetUnit
: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
67 * Returns the value computed by the animation's "method".
69 * @param {String} attr The name of the attribute.
70 * @param {Number} start The value this attribute should start from for this animation.
71 * @param {Number} end The value this attribute should end at for this animation.
72 * @return {Number} The Value to be applied to the attribute.
74 doMethod: function(attr
, start
, end
) {
75 return this.method(this.currentFrame
, start
, end
- start
, this.totalFrames
);
79 * Applies a value to an attribute.
80 * @method setAttribute
81 * @param {String} attr The name of the attribute.
82 * @param {Number} val The value to be applied to the attribute.
83 * @param {String} unit The unit ('px', '%', etc.) of the value.
85 setAttribute: function(attr
, val
, unit
) {
86 if ( this.patterns
.noNegatives
.test(attr
) ) {
87 val
= (val
> 0) ? val
: 0;
90 YAHOO
.util
.Dom
.setStyle(this.getEl(), attr
, val
+ unit
);
94 * Returns current value of the attribute.
95 * @method getAttribute
96 * @param {String} attr The name of the attribute.
97 * @return {Number} val The current value of the attribute.
99 getAttribute: function(attr
) {
100 var el
= this.getEl();
101 var val
= YAHOO
.util
.Dom
.getStyle(el
, attr
);
103 if (val
!== 'auto' && !this.patterns
.offsetUnit
.test(val
)) {
104 return parseFloat(val
);
107 var a
= this.patterns
.offsetAttribute
.exec(attr
) || [];
108 var pos
= !!( a
[3] ); // top or left
109 var box
= !!( a
[2] ); // width or height
111 // use offsets for width/height and abs pos top/left
112 if ( box
|| (YAHOO
.util
.Dom
.getStyle(el
, 'position') == 'absolute' && pos
) ) {
113 val
= el
['offset' + a
[0].charAt(0).toUpperCase() + a
[0].substr(1)];
114 } else { // default to zero for other 'auto'
122 * Returns the unit to use when none is supplied.
123 * @method getDefaultUnit
124 * @param {attr} attr The name of the attribute.
125 * @return {String} The default unit to be used.
127 getDefaultUnit: function(attr
) {
128 if ( this.patterns
.defaultUnit
.test(attr
) ) {
136 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
137 * @method setRuntimeAttribute
138 * @param {Object} attr The attribute object
141 setRuntimeAttribute: function(attr
) {
144 var attributes
= this.attributes
;
146 this.runtimeAttributes
[attr
] = {};
148 var isset = function(prop
) {
149 return (typeof prop
!== 'undefined');
152 if ( !isset(attributes
[attr
]['to']) && !isset(attributes
[attr
]['by']) ) {
153 return false; // note return; nothing to animate to
156 start
= ( isset(attributes
[attr
]['from']) ) ? attributes
[attr
]['from'] : this.getAttribute(attr
);
158 // To beats by, per SMIL 2.1 spec
159 if ( isset(attributes
[attr
]['to']) ) {
160 end
= attributes
[attr
]['to'];
161 } else if ( isset(attributes
[attr
]['by']) ) {
162 if (start
.constructor == Array
) {
164 for (var i
= 0, len
= start
.length
; i
< len
; ++i
) {
165 end
[i
] = start
[i
] + attributes
[attr
]['by'][i
] * 1; // times 1 to cast "by"
168 end
= start
+ attributes
[attr
]['by'] * 1;
172 this.runtimeAttributes
[attr
].start
= start
;
173 this.runtimeAttributes
[attr
].end
= end
;
175 // set units if needed
176 this.runtimeAttributes
[attr
].unit
= ( isset(attributes
[attr
].unit
) ) ?
177 attributes
[attr
]['unit'] : this.getDefaultUnit(attr
);
182 * Constructor for Anim instance.
184 * @param {String | HTMLElement} el Reference to the element that will be animated
185 * @param {Object} attributes The attribute(s) to be animated.
186 * Each attribute is an object with at minimum a "to" or "by" member defined.
187 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
188 * All attribute names use camelCase.
189 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
190 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
192 init: function(el
, attributes
, duration
, method
) {
194 * Whether or not the animation is running.
195 * @property isAnimated
199 var isAnimated
= false;
202 * A Date object that is created when the animation begins.
203 * @property startTime
207 var startTime
= null;
210 * The number of frames this animation was able to execute.
211 * @property actualFrames
215 var actualFrames
= 0;
218 * The element to be animated.
223 el
= YAHOO
.util
.Dom
.get(el
);
226 * The collection of attributes to be animated.
227 * Each attribute must have at least a "to" or "by" defined in order to animate.
228 * If "to" is supplied, the animation will end with the attribute at that value.
229 * If "by" is supplied, the animation will end at that value plus its starting value.
230 * If both are supplied, "to" is used, and "by" is ignored.
231 * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values).
232 * @property attributes
235 this.attributes
= attributes
|| {};
238 * The length of the animation. Defaults to "1" (second).
242 this.duration
= !YAHOO
.lang
.isUndefined(duration
) ? duration
: 1;
245 * The method that will provide values to the attribute(s) during the animation.
246 * Defaults to "YAHOO.util.Easing.easeNone".
250 this.method
= method
|| YAHOO
.util
.Easing
.easeNone
;
253 * Whether or not the duration should be treated as seconds.
255 * @property useSeconds
258 this.useSeconds
= true; // default to seconds
261 * The location of the current animation on the timeline.
262 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
263 * @property currentFrame
266 this.currentFrame
= 0;
269 * The total number of frames to be executed.
270 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
271 * @property totalFrames
274 this.totalFrames
= YAHOO
.util
.AnimMgr
.fps
;
277 * Changes the animated element
280 this.setEl = function(element
) {
281 el
= YAHOO
.util
.Dom
.get(element
);
285 * Returns a reference to the animated element.
287 * @return {HTMLElement}
289 this.getEl = function() { return el
; };
292 * Checks whether the element is currently animated.
294 * @return {Boolean} current value of isAnimated.
296 this.isAnimated = function() {
301 * Returns the animation start time.
302 * @method getStartTime
303 * @return {Date} current value of startTime.
305 this.getStartTime = function() {
309 this.runtimeAttributes
= {};
312 logger
.log = function() {YAHOO
.log
.apply(window
, arguments
)};
314 logger
.log('creating new instance of ' + this);
317 * Starts the animation by registering it with the animation manager.
320 this.animate = function() {
321 if ( this.isAnimated() ) {
325 this.currentFrame
= 0;
327 this.totalFrames
= ( this.useSeconds
) ? Math
.ceil(YAHOO
.util
.AnimMgr
.fps
* this.duration
) : this.duration
;
329 if (this.duration
=== 0 && this.useSeconds
) {
330 this.totalFrames
= 1; // jump to last frame if no duration
332 YAHOO
.util
.AnimMgr
.registerElement(this);
337 * Stops the animation. Normally called by AnimMgr when animation completes.
339 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
341 this.stop = function(finish
) {
343 this.currentFrame
= this.totalFrames
;
344 this._onTween
.fire();
346 YAHOO
.util
.AnimMgr
.stop(this);
349 var onStart = function() {
352 this.runtimeAttributes
= {};
353 for (var attr
in this.attributes
) {
354 this.setRuntimeAttribute(attr
);
359 startTime
= new Date();
363 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
367 var onTween = function() {
369 duration
: new Date() - this.getStartTime(),
370 currentFrame
: this.currentFrame
373 data
.toString = function() {
375 'duration: ' + data
.duration
+
376 ', currentFrame: ' + data
.currentFrame
380 this.onTween
.fire(data
);
382 var runtimeAttributes
= this.runtimeAttributes
;
384 for (var attr
in runtimeAttributes
) {
385 this.setAttribute(attr
, this.doMethod(attr
, runtimeAttributes
[attr
].start
, runtimeAttributes
[attr
].end
), runtimeAttributes
[attr
].unit
);
391 var onComplete = function() {
392 var actual_duration
= (new Date() - startTime
) / 1000 ;
395 duration
: actual_duration
,
396 frames
: actualFrames
,
397 fps
: actualFrames
/ actual_duration
400 data
.toString = function() {
402 'duration: ' + data
.duration
+
403 ', frames: ' + data
.frames
+
410 this.onComplete
.fire(data
);
414 * Custom event that fires after onStart, useful in subclassing
417 this._onStart
= new YAHOO
.util
.CustomEvent('_start', this, true);
420 * Custom event that fires when animation begins
421 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
424 this.onStart
= new YAHOO
.util
.CustomEvent('start', this);
427 * Custom event that fires between each frame
428 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
431 this.onTween
= new YAHOO
.util
.CustomEvent('tween', this);
434 * Custom event that fires after onTween
437 this._onTween
= new YAHOO
.util
.CustomEvent('_tween', this, true);
440 * Custom event that fires when animation ends
441 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
444 this.onComplete
= new YAHOO
.util
.CustomEvent('complete', this);
446 * Custom event that fires after onComplete
449 this._onComplete
= new YAHOO
.util
.CustomEvent('_complete', this, true);
451 this._onStart
.subscribe(onStart
);
452 this._onTween
.subscribe(onTween
);
453 this._onComplete
.subscribe(onComplete
);
458 * Handles animation queueing and threading.
459 * Used by Anim and subclasses.
461 * @namespace YAHOO.util
463 YAHOO
.util
.AnimMgr
= new function() {
465 * Reference to the animation Interval.
473 * The current queue of registered animation objects.
481 * The number of active animations.
482 * @property tweenCount
489 * Base frame rate (frames per second).
490 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
498 * Interval delay in milliseconds, defaults to fastest possible.
506 * Adds an animation instance to the animation queue.
507 * All animation instances must be registered in order to animate.
508 * @method registerElement
509 * @param {object} tween The Anim instance to be be registered
511 this.registerElement = function(tween
) {
512 queue
[queue
.length
] = tween
;
514 tween
._onStart
.fire();
519 * removes an animation instance from the animation queue.
520 * All animation instances must be registered in order to animate.
522 * @param {object} tween The Anim instance to be be registered
523 * @param {Int} index The index of the Anim instance
526 this.unRegister = function(tween
, index
) {
527 tween
._onComplete
.fire();
528 index
= index
|| getIndex(tween
);
533 queue
.splice(index
, 1);
536 if (tweenCount
<= 0) {
544 * Starts the animation thread.
545 * Only one thread can run at a time.
548 this.start = function() {
549 if (thread
=== null) {
550 thread
= setInterval(this.run
, this.delay
);
555 * Stops the animation thread or a specific animation instance.
557 * @param {object} tween A specific Anim instance to stop (optional)
558 * If no instance given, Manager stops thread and all animations.
560 this.stop = function(tween
) {
562 clearInterval(thread
);
564 for (var i
= 0, len
= queue
.length
; i
< len
; ++i
) {
565 if ( queue
[0].isAnimated() ) {
566 this.unRegister(queue
[0], 0);
575 this.unRegister(tween
);
580 * Called per Interval to handle each animation frame.
583 this.run = function() {
584 for (var i
= 0, len
= queue
.length
; i
< len
; ++i
) {
585 var tween
= queue
[i
];
586 if ( !tween
|| !tween
.isAnimated() ) { continue; }
588 if (tween
.currentFrame
< tween
.totalFrames
|| tween
.totalFrames
=== null)
590 tween
.currentFrame
+= 1;
592 if (tween
.useSeconds
) {
595 tween
._onTween
.fire();
597 else { YAHOO
.util
.AnimMgr
.stop(tween
, i
); }
601 var getIndex = function(anim
) {
602 for (var i
= 0, len
= queue
.length
; i
< len
; ++i
) {
603 if (queue
[i
] == anim
) {
604 return i
; // note return;
611 * On the fly frame correction to keep animation on time.
612 * @method correctFrame
614 * @param {Object} tween The Anim instance being corrected.
616 var correctFrame = function(tween
) {
617 var frames
= tween
.totalFrames
;
618 var frame
= tween
.currentFrame
;
619 var expected
= (tween
.currentFrame
* tween
.duration
* 1000 / tween
.totalFrames
);
620 var elapsed
= (new Date() - tween
.getStartTime());
623 if (elapsed
< tween
.duration
* 1000) { // check if falling behind
624 tweak
= Math
.round((elapsed
/ expected
- 1) * tween
.currentFrame
);
625 } else { // went over duration, so jump to end
626 tweak
= frames
- (frame
+ 1);
628 if (tweak
> 0 && isFinite(tweak
)) { // adjust if needed
629 if (tween
.currentFrame
+ tweak
>= frames
) {// dont go past last frame
630 tweak
= frames
- (frame
+ 1);
633 tween
.currentFrame
+= tweak
;
638 * Used to calculate Bezier splines for any number of control points.
640 * @namespace YAHOO.util
643 YAHOO
.util
.Bezier
= new function() {
645 * Get the current position of the animated element based on t.
646 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
647 * At least 2 points are required (start and end).
648 * First point is start. Last point is end.
649 * Additional control points are optional.
650 * @method getPosition
651 * @param {Array} points An array containing Bezier points
652 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
653 * @return {Array} An array containing int x and y member data
655 this.getPosition = function(points
, t
) {
656 var n
= points
.length
;
659 for (var i
= 0; i
< n
; ++i
){
660 tmp
[i
] = [points
[i
][0], points
[i
][1]]; // save input
663 for (var j
= 1; j
< n
; ++j
) {
664 for (i
= 0; i
< n
- j
; ++i
) {
665 tmp
[i
][0] = (1 - t
) * tmp
[i
][0] + t
* tmp
[parseInt(i
+ 1, 10)][0];
666 tmp
[i
][1] = (1 - t
) * tmp
[i
][1] + t
* tmp
[parseInt(i
+ 1, 10)][1];
670 return [ tmp
[0][0], tmp
[0][1] ];
676 * Anim subclass for color transitions.
677 * <p>Usage: <code>var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);</code> Color values can be specified with either 112233, #112233,
678 * [255,255,255], or rgb(255,255,255)</p>
680 * @namespace YAHOO.util
681 * @requires YAHOO.util.Anim
682 * @requires YAHOO.util.AnimMgr
683 * @requires YAHOO.util.Easing
684 * @requires YAHOO.util.Bezier
685 * @requires YAHOO.util.Dom
686 * @requires YAHOO.util.Event
688 * @extends YAHOO.util.Anim
689 * @param {HTMLElement | String} el Reference to the element that will be animated
690 * @param {Object} attributes The attribute(s) to be animated.
691 * Each attribute is an object with at minimum a "to" or "by" member defined.
692 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
693 * All attribute names use camelCase.
694 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
695 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
697 YAHOO
.util
.ColorAnim = function(el
, attributes
, duration
, method
) {
698 YAHOO
.util
.ColorAnim
.superclass
.constructor.call(this, el
, attributes
, duration
, method
);
701 YAHOO
.extend(YAHOO
.util
.ColorAnim
, YAHOO
.util
.Anim
);
705 var superclass
= Y
.ColorAnim
.superclass
;
706 var proto
= Y
.ColorAnim
.prototype;
708 proto
.toString = function() {
709 var el
= this.getEl();
710 var id
= el
.id
|| el
.tagName
;
711 return ("ColorAnim " + id
);
714 proto
.patterns
.color
= /color$/i;
715 proto
.patterns
.rgb
= /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
716 proto
.patterns
.hex
= /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
717 proto
.patterns
.hex3
= /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
718 proto
.patterns
.transparent
= /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
721 * Attempts to parse the given string and return a 3-tuple.
723 * @param {String} s The string to parse.
724 * @return {Array} The 3-tuple of rgb values.
726 proto
.parseColor = function(s
) {
727 if (s
.length
== 3) { return s
; }
729 var c
= this.patterns
.hex
.exec(s
);
730 if (c
&& c
.length
== 4) {
731 return [ parseInt(c
[1], 16), parseInt(c
[2], 16), parseInt(c
[3], 16) ];
734 c
= this.patterns
.rgb
.exec(s
);
735 if (c
&& c
.length
== 4) {
736 return [ parseInt(c
[1], 10), parseInt(c
[2], 10), parseInt(c
[3], 10) ];
739 c
= this.patterns
.hex3
.exec(s
);
740 if (c
&& c
.length
== 4) {
741 return [ parseInt(c
[1] + c
[1], 16), parseInt(c
[2] + c
[2], 16), parseInt(c
[3] + c
[3], 16) ];
747 proto
.getAttribute = function(attr
) {
748 var el
= this.getEl();
749 if ( this.patterns
.color
.test(attr
) ) {
750 var val
= YAHOO
.util
.Dom
.getStyle(el
, attr
);
752 if (this.patterns
.transparent
.test(val
)) { // bgcolor default
753 var parent
= el
.parentNode
; // try and get from an ancestor
754 val
= Y
.Dom
.getStyle(parent
, attr
);
756 while (parent
&& this.patterns
.transparent
.test(val
)) {
757 parent
= parent
.parentNode
;
758 val
= Y
.Dom
.getStyle(parent
, attr
);
759 if (parent
.tagName
.toUpperCase() == 'HTML') {
765 val
= superclass
.getAttribute
.call(this, attr
);
771 proto
.doMethod = function(attr
, start
, end
) {
774 if ( this.patterns
.color
.test(attr
) ) {
776 for (var i
= 0, len
= start
.length
; i
< len
; ++i
) {
777 val
[i
] = superclass
.doMethod
.call(this, attr
, start
[i
], end
[i
]);
780 val
= 'rgb('+Math
.floor(val
[0])+','+Math
.floor(val
[1])+','+Math
.floor(val
[2])+')';
783 val
= superclass
.doMethod
.call(this, attr
, start
, end
);
789 proto
.setRuntimeAttribute = function(attr
) {
790 superclass
.setRuntimeAttribute
.call(this, attr
);
792 if ( this.patterns
.color
.test(attr
) ) {
793 var attributes
= this.attributes
;
794 var start
= this.parseColor(this.runtimeAttributes
[attr
].start
);
795 var end
= this.parseColor(this.runtimeAttributes
[attr
].end
);
796 // fix colors if going "by"
797 if ( typeof attributes
[attr
]['to'] === 'undefined' && typeof attributes
[attr
]['by'] !== 'undefined' ) {
798 end
= this.parseColor(attributes
[attr
].by
);
800 for (var i
= 0, len
= start
.length
; i
< len
; ++i
) {
801 end
[i
] = start
[i
] + end
[i
];
805 this.runtimeAttributes
[attr
].start
= start
;
806 this.runtimeAttributes
[attr
].end
= end
;
811 TERMS OF USE - EASING EQUATIONS
812 Open source under the BSD License.
813 Copyright 2001 Robert Penner All rights reserved.
815 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
817 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
818 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
819 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
821 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
825 * Singleton that determines how an animation proceeds from start to end.
827 * @namespace YAHOO.util
830 YAHOO
.util
.Easing
= {
833 * Uniform speed between points.
835 * @param {Number} t Time value used to compute current value
836 * @param {Number} b Starting value
837 * @param {Number} c Delta between start and end values
838 * @param {Number} d Total length of animation
839 * @return {Number} The computed value for the current animation frame
841 easeNone: function (t
, b
, c
, d
) {
846 * Begins slowly and accelerates towards end. (quadratic)
848 * @param {Number} t Time value used to compute current value
849 * @param {Number} b Starting value
850 * @param {Number} c Delta between start and end values
851 * @param {Number} d Total length of animation
852 * @return {Number} The computed value for the current animation frame
854 easeIn: function (t
, b
, c
, d
) {
855 return c
*(t
/=d
)*t
+ b
;
859 * Begins quickly and decelerates towards end. (quadratic)
861 * @param {Number} t Time value used to compute current value
862 * @param {Number} b Starting value
863 * @param {Number} c Delta between start and end values
864 * @param {Number} d Total length of animation
865 * @return {Number} The computed value for the current animation frame
867 easeOut: function (t
, b
, c
, d
) {
868 return -c
*(t
/=d
)*(t
-2) + b
;
872 * Begins slowly and decelerates towards end. (quadratic)
874 * @param {Number} t Time value used to compute current value
875 * @param {Number} b Starting value
876 * @param {Number} c Delta between start and end values
877 * @param {Number} d Total length of animation
878 * @return {Number} The computed value for the current animation frame
880 easeBoth: function (t
, b
, c
, d
) {
885 return -c
/2 * ((--t
)*(t
-2) - 1) + b
;
889 * Begins slowly and accelerates towards end. (quartic)
890 * @method easeInStrong
891 * @param {Number} t Time value used to compute current value
892 * @param {Number} b Starting value
893 * @param {Number} c Delta between start and end values
894 * @param {Number} d Total length of animation
895 * @return {Number} The computed value for the current animation frame
897 easeInStrong: function (t
, b
, c
, d
) {
898 return c
*(t
/=d
)*t
*t
*t
+ b
;
902 * Begins quickly and decelerates towards end. (quartic)
903 * @method easeOutStrong
904 * @param {Number} t Time value used to compute current value
905 * @param {Number} b Starting value
906 * @param {Number} c Delta between start and end values
907 * @param {Number} d Total length of animation
908 * @return {Number} The computed value for the current animation frame
910 easeOutStrong: function (t
, b
, c
, d
) {
911 return -c
* ((t
=t
/d
-1)*t
*t
*t
- 1) + b
;
915 * Begins slowly and decelerates towards end. (quartic)
916 * @method easeBothStrong
917 * @param {Number} t Time value used to compute current value
918 * @param {Number} b Starting value
919 * @param {Number} c Delta between start and end values
920 * @param {Number} d Total length of animation
921 * @return {Number} The computed value for the current animation frame
923 easeBothStrong: function (t
, b
, c
, d
) {
925 return c
/2*t
*t
*t
*t
+ b
;
928 return -c
/2 * ((t
-=2)*t
*t
*t
- 2) + b
;
932 * Snap in elastic effect.
934 * @param {Number} t Time value used to compute current value
935 * @param {Number} b Starting value
936 * @param {Number} c Delta between start and end values
937 * @param {Number} d Total length of animation
938 * @param {Number} a Amplitude (optional)
939 * @param {Number} p Period (optional)
940 * @return {Number} The computed value for the current animation frame
943 elasticIn: function (t
, b
, c
, d
, a
, p
) {
947 if ( (t
/= d
) == 1 ) {
954 if (!a
|| a
< Math
.abs(c
)) {
959 var s
= p
/(2*Math.PI) * Math.asin (c/a);
962 return -(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
966 * Snap out elastic effect.
968 * @param {Number} t Time value used to compute current value
969 * @param {Number} b Starting value
970 * @param {Number} c Delta between start and end values
971 * @param {Number} d Total length of animation
972 * @param {Number} a Amplitude (optional)
973 * @param {Number} p Period (optional)
974 * @return {Number} The computed value for the current animation frame
976 elasticOut: function (t
, b
, c
, d
, a
, p
) {
980 if ( (t
/= d
) == 1 ) {
987 if (!a
|| a
< Math
.abs(c
)) {
992 var s
= p
/(2*Math.PI) * Math.asin (c/a);
995 return a
*Math
.pow(2,-10*t
) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
) + c
+ b
;
999 * Snap both elastic effect.
1000 * @method elasticBoth
1001 * @param {Number} t Time value used to compute current value
1002 * @param {Number} b Starting value
1003 * @param {Number} c Delta between start and end values
1004 * @param {Number} d Total length of animation
1005 * @param {Number} a Amplitude (optional)
1006 * @param {Number} p Period (optional)
1007 * @return {Number} The computed value for the current animation frame
1009 elasticBoth: function (t
, b
, c
, d
, a
, p
) {
1014 if ( (t
/= d/2) == 2 ) {
1022 if ( !a
|| a
< Math
.abs(c
) ) {
1027 var s
= p
/(2*Math.PI) * Math.asin (c/a);
1031 return -.5*(a
*Math
.pow(2,10*(t
-=1)) *
1032 Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
1034 return a
*Math
.pow(2,-10*(t
-=1)) *
1035 Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)*.5 + c
+ b
;
1040 * Backtracks slightly, then reverses direction and moves to end.
1042 * @param {Number} t Time value used to compute current value
1043 * @param {Number} b Starting value
1044 * @param {Number} c Delta between start and end values
1045 * @param {Number} d Total length of animation
1046 * @param {Number} s Overshoot (optional)
1047 * @return {Number} The computed value for the current animation frame
1049 backIn: function (t
, b
, c
, d
, s
) {
1050 if (typeof s
== 'undefined') {
1053 return c
*(t
/=d
)*t
*((s
+1)*t
- s
) + b
;
1057 * Overshoots end, then reverses and comes back to end.
1059 * @param {Number} t Time value used to compute current value
1060 * @param {Number} b Starting value
1061 * @param {Number} c Delta between start and end values
1062 * @param {Number} d Total length of animation
1063 * @param {Number} s Overshoot (optional)
1064 * @return {Number} The computed value for the current animation frame
1066 backOut: function (t
, b
, c
, d
, s
) {
1067 if (typeof s
== 'undefined') {
1070 return c
*((t
=t
/d
-1)*t
*((s
+1)*t
+ s
) + 1) + b
;
1074 * Backtracks slightly, then reverses direction, overshoots end,
1075 * then reverses and comes back to end.
1077 * @param {Number} t Time value used to compute current value
1078 * @param {Number} b Starting value
1079 * @param {Number} c Delta between start and end values
1080 * @param {Number} d Total length of animation
1081 * @param {Number} s Overshoot (optional)
1082 * @return {Number} The computed value for the current animation frame
1084 backBoth: function (t
, b
, c
, d
, s
) {
1085 if (typeof s
== 'undefined') {
1089 if ((t
/= d/2 ) < 1) {
1090 return c
/2*(t
*t
*(((s
*=(1.525))+1)*t
- s
)) + b
;
1092 return c
/2*((t
-=2)*t
*(((s
*=(1.525))+1)*t
+ s
) + 2) + b
;
1096 * Bounce off of start.
1098 * @param {Number} t Time value used to compute current value
1099 * @param {Number} b Starting value
1100 * @param {Number} c Delta between start and end values
1101 * @param {Number} d Total length of animation
1102 * @return {Number} The computed value for the current animation frame
1104 bounceIn: function (t
, b
, c
, d
) {
1105 return c
- YAHOO
.util
.Easing
.bounceOut(d
-t
, 0, c
, d
) + b
;
1111 * @param {Number} t Time value used to compute current value
1112 * @param {Number} b Starting value
1113 * @param {Number} c Delta between start and end values
1114 * @param {Number} d Total length of animation
1115 * @return {Number} The computed value for the current animation frame
1117 bounceOut: function (t
, b
, c
, d
) {
1118 if ((t
/=d) < (1/2.75)) {
1119 return c
*(7.5625*t
*t
) + b
;
1120 } else if (t
< (2/2.75)) {
1121 return c
*(7.5625*(t
-=(1.5/2.75))*t
+ .75) + b
;
1122 } else if (t
< (2.5/2.75)) {
1123 return c
*(7.5625*(t
-=(2.25/2.75))*t
+ .9375) + b
;
1125 return c
*(7.5625*(t
-=(2.625/2.75))*t
+ .984375) + b
;
1129 * Bounces off start and end.
1130 * @method bounceBoth
1131 * @param {Number} t Time value used to compute current value
1132 * @param {Number} b Starting value
1133 * @param {Number} c Delta between start and end values
1134 * @param {Number} d Total length of animation
1135 * @return {Number} The computed value for the current animation frame
1137 bounceBoth: function (t
, b
, c
, d
) {
1139 return YAHOO
.util
.Easing
.bounceIn(t
*2, 0, c
, d
) * .5 + b
;
1141 return YAHOO
.util
.Easing
.bounceOut(t
*2-d
, 0, c
, d
) * .5 + c
*.5 + b
;
1147 * Anim subclass for moving elements along a path defined by the "points"
1148 * member of "attributes". All "points" are arrays with x, y coordinates.
1149 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1151 * @namespace YAHOO.util
1152 * @requires YAHOO.util.Anim
1153 * @requires YAHOO.util.AnimMgr
1154 * @requires YAHOO.util.Easing
1155 * @requires YAHOO.util.Bezier
1156 * @requires YAHOO.util.Dom
1157 * @requires YAHOO.util.Event
1158 * @requires YAHOO.util.CustomEvent
1160 * @extends YAHOO.util.Anim
1161 * @param {String | HTMLElement} el Reference to the element that will be animated
1162 * @param {Object} attributes The attribute(s) to be animated.
1163 * Each attribute is an object with at minimum a "to" or "by" member defined.
1164 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1165 * All attribute names use camelCase.
1166 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1167 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1169 YAHOO
.util
.Motion = function(el
, attributes
, duration
, method
) {
1170 if (el
) { // dont break existing subclasses not using YAHOO.extend
1171 YAHOO
.util
.Motion
.superclass
.constructor.call(this, el
, attributes
, duration
, method
);
1175 YAHOO
.extend(YAHOO
.util
.Motion
, YAHOO
.util
.ColorAnim
);
1179 var superclass
= Y
.Motion
.superclass
;
1180 var proto
= Y
.Motion
.prototype;
1182 proto
.toString = function() {
1183 var el
= this.getEl();
1184 var id
= el
.id
|| el
.tagName
;
1185 return ("Motion " + id
);
1188 proto
.patterns
.points
= /^points$/i;
1190 proto
.setAttribute = function(attr
, val
, unit
) {
1191 if ( this.patterns
.points
.test(attr
) ) {
1192 unit
= unit
|| 'px';
1193 superclass
.setAttribute
.call(this, 'left', val
[0], unit
);
1194 superclass
.setAttribute
.call(this, 'top', val
[1], unit
);
1196 superclass
.setAttribute
.call(this, attr
, val
, unit
);
1200 proto
.getAttribute = function(attr
) {
1201 if ( this.patterns
.points
.test(attr
) ) {
1203 superclass
.getAttribute
.call(this, 'left'),
1204 superclass
.getAttribute
.call(this, 'top')
1207 val
= superclass
.getAttribute
.call(this, attr
);
1213 proto
.doMethod = function(attr
, start
, end
) {
1216 if ( this.patterns
.points
.test(attr
) ) {
1217 var t
= this.method(this.currentFrame
, 0, 100, this.totalFrames
) / 100;
1218 val
= Y
.Bezier
.getPosition(this.runtimeAttributes
[attr
], t
);
1220 val
= superclass
.doMethod
.call(this, attr
, start
, end
);
1225 proto
.setRuntimeAttribute = function(attr
) {
1226 if ( this.patterns
.points
.test(attr
) ) {
1227 var el
= this.getEl();
1228 var attributes
= this.attributes
;
1230 var control
= attributes
['points']['control'] || [];
1234 if (control
.length
> 0 && !(control
[0] instanceof Array
) ) { // could be single point or array of points
1235 control
= [control
];
1236 } else { // break reference to attributes.points.control
1238 for (i
= 0, len
= control
.length
; i
< len
; ++i
) {
1239 tmp
[i
] = control
[i
];
1244 if (Y
.Dom
.getStyle(el
, 'position') == 'static') { // default to relative
1245 Y
.Dom
.setStyle(el
, 'position', 'relative');
1248 if ( isset(attributes
['points']['from']) ) {
1249 Y
.Dom
.setXY(el
, attributes
['points']['from']); // set position to from point
1251 else { Y
.Dom
.setXY( el
, Y
.Dom
.getXY(el
) ); } // set it to current position
1253 start
= this.getAttribute('points'); // get actual top & left
1255 // TO beats BY, per SMIL 2.1 spec
1256 if ( isset(attributes
['points']['to']) ) {
1257 end
= translateValues
.call(this, attributes
['points']['to'], start
);
1259 var pageXY
= Y
.Dom
.getXY(this.getEl());
1260 for (i
= 0, len
= control
.length
; i
< len
; ++i
) {
1261 control
[i
] = translateValues
.call(this, control
[i
], start
);
1265 } else if ( isset(attributes
['points']['by']) ) {
1266 end
= [ start
[0] + attributes
['points']['by'][0], start
[1] + attributes
['points']['by'][1] ];
1268 for (i
= 0, len
= control
.length
; i
< len
; ++i
) {
1269 control
[i
] = [ start
[0] + control
[i
][0], start
[1] + control
[i
][1] ];
1273 this.runtimeAttributes
[attr
] = [start
];
1275 if (control
.length
> 0) {
1276 this.runtimeAttributes
[attr
] = this.runtimeAttributes
[attr
].concat(control
);
1279 this.runtimeAttributes
[attr
][this.runtimeAttributes
[attr
].length
] = end
;
1282 superclass
.setRuntimeAttribute
.call(this, attr
);
1286 var translateValues = function(val
, start
) {
1287 var pageXY
= Y
.Dom
.getXY(this.getEl());
1288 val
= [ val
[0] - pageXY
[0] + start
[0], val
[1] - pageXY
[1] + start
[1] ];
1293 var isset = function(prop
) {
1294 return (typeof prop
!== 'undefined');
1299 * Anim subclass for scrolling elements to a position defined by the "scroll"
1300 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1301 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1303 * @namespace YAHOO.util
1304 * @requires YAHOO.util.Anim
1305 * @requires YAHOO.util.AnimMgr
1306 * @requires YAHOO.util.Easing
1307 * @requires YAHOO.util.Bezier
1308 * @requires YAHOO.util.Dom
1309 * @requires YAHOO.util.Event
1310 * @requires YAHOO.util.CustomEvent
1311 * @extends YAHOO.util.Anim
1313 * @param {String or HTMLElement} el Reference to the element that will be animated
1314 * @param {Object} attributes The attribute(s) to be animated.
1315 * Each attribute is an object with at minimum a "to" or "by" member defined.
1316 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1317 * All attribute names use camelCase.
1318 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1319 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1321 YAHOO
.util
.Scroll = function(el
, attributes
, duration
, method
) {
1322 if (el
) { // dont break existing subclasses not using YAHOO.extend
1323 YAHOO
.util
.Scroll
.superclass
.constructor.call(this, el
, attributes
, duration
, method
);
1327 YAHOO
.extend(YAHOO
.util
.Scroll
, YAHOO
.util
.ColorAnim
);
1331 var superclass
= Y
.Scroll
.superclass
;
1332 var proto
= Y
.Scroll
.prototype;
1334 proto
.toString = function() {
1335 var el
= this.getEl();
1336 var id
= el
.id
|| el
.tagName
;
1337 return ("Scroll " + id
);
1340 proto
.doMethod = function(attr
, start
, end
) {
1343 if (attr
== 'scroll') {
1345 this.method(this.currentFrame
, start
[0], end
[0] - start
[0], this.totalFrames
),
1346 this.method(this.currentFrame
, start
[1], end
[1] - start
[1], this.totalFrames
)
1350 val
= superclass
.doMethod
.call(this, attr
, start
, end
);
1355 proto
.getAttribute = function(attr
) {
1357 var el
= this.getEl();
1359 if (attr
== 'scroll') {
1360 val
= [ el
.scrollLeft
, el
.scrollTop
];
1362 val
= superclass
.getAttribute
.call(this, attr
);
1368 proto
.setAttribute = function(attr
, val
, unit
) {
1369 var el
= this.getEl();
1371 if (attr
== 'scroll') {
1372 el
.scrollLeft
= val
[0];
1373 el
.scrollTop
= val
[1];
1375 superclass
.setAttribute
.call(this, attr
, val
, unit
);
1379 YAHOO
.register("animation", YAHOO
.util
.Anim
, {version
: "2.3.0", build
: "442"});