|
1 /* |
|
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved. |
|
3 Code licensed under the BSD License: |
|
4 http://developer.yahoo.net/yui/license.txt |
|
5 version: 3.0.0 |
|
6 build: 1549 |
|
7 */ |
|
8 YUI.add('anim-base', function(Y) { |
|
9 |
|
10 /** |
|
11 * The Animation Utility provides an API for creating advanced transitions. |
|
12 * @module anim |
|
13 */ |
|
14 |
|
15 /** |
|
16 * Provides the base Anim class, for animating numeric properties. |
|
17 * |
|
18 * @module anim |
|
19 * @submodule anim-base |
|
20 */ |
|
21 |
|
22 /** |
|
23 * A class for constructing animation instances. |
|
24 * @class Anim |
|
25 * @for Anim |
|
26 * @constructor |
|
27 * @extends Base |
|
28 */ |
|
29 |
|
30 var RUNNING = 'running', |
|
31 START_TIME = 'startTime', |
|
32 ELAPSED_TIME = 'elapsedTime', |
|
33 /** |
|
34 * @for Anim |
|
35 * @event start |
|
36 * @description fires when an animation begins. |
|
37 * @param {Event} ev The start event. |
|
38 * @type Event.Custom |
|
39 */ |
|
40 START = 'start', |
|
41 |
|
42 /** |
|
43 * @event tween |
|
44 * @description fires every frame of the animation. |
|
45 * @param {Event} ev The tween event. |
|
46 * @type Event.Custom |
|
47 */ |
|
48 TWEEN = 'tween', |
|
49 |
|
50 /** |
|
51 * @event end |
|
52 * @description fires after the animation completes. |
|
53 * @param {Event} ev The end event. |
|
54 * @type Event.Custom |
|
55 */ |
|
56 END = 'end', |
|
57 NODE = 'node', |
|
58 PAUSED = 'paused', |
|
59 REVERSE = 'reverse', // TODO: cleanup |
|
60 ITERATION_COUNT = 'iterationCount', |
|
61 |
|
62 NUM = Number; |
|
63 |
|
64 var _running = {}, |
|
65 _instances = {}, |
|
66 _timer; |
|
67 |
|
68 Y.Anim = function() { |
|
69 Y.Anim.superclass.constructor.apply(this, arguments); |
|
70 _instances[Y.stamp(this)] = this; |
|
71 }; |
|
72 |
|
73 Y.Anim.NAME = 'anim'; |
|
74 |
|
75 /** |
|
76 * Regex of properties that should use the default unit. |
|
77 * |
|
78 * @property RE_DEFAULT_UNIT |
|
79 * @static |
|
80 */ |
|
81 Y.Anim.RE_DEFAULT_UNIT = /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i; |
|
82 |
|
83 /** |
|
84 * The default unit to use with properties that pass the RE_DEFAULT_UNIT test. |
|
85 * |
|
86 * @property DEFAULT_UNIT |
|
87 * @static |
|
88 */ |
|
89 Y.Anim.DEFAULT_UNIT = 'px'; |
|
90 |
|
91 Y.Anim.DEFAULT_EASING = function (t, b, c, d) { |
|
92 return c * t / d + b; // linear easing |
|
93 }; |
|
94 |
|
95 /** |
|
96 * Bucket for custom getters and setters |
|
97 * |
|
98 * @property behaviors |
|
99 * @static |
|
100 */ |
|
101 Y.Anim.behaviors = { |
|
102 left: { |
|
103 get: function(anim, attr) { |
|
104 return anim._getOffset(attr); |
|
105 } |
|
106 } |
|
107 }; |
|
108 |
|
109 Y.Anim.behaviors.top = Y.Anim.behaviors.left; |
|
110 |
|
111 /** |
|
112 * The default setter to use when setting object properties. |
|
113 * |
|
114 * @property DEFAULT_SETTER |
|
115 * @static |
|
116 */ |
|
117 Y.Anim.DEFAULT_SETTER = function(anim, att, from, to, elapsed, duration, fn, unit) { |
|
118 unit = unit || ''; |
|
119 anim._node.setStyle(att, fn(elapsed, NUM(from), NUM(to) - NUM(from), duration) + unit); |
|
120 }; |
|
121 |
|
122 /** |
|
123 * The default getter to use when getting object properties. |
|
124 * |
|
125 * @property DEFAULT_GETTER |
|
126 * @static |
|
127 */ |
|
128 Y.Anim.DEFAULT_GETTER = function(anim, prop) { |
|
129 return anim._node.getComputedStyle(prop); |
|
130 }; |
|
131 |
|
132 Y.Anim.ATTRS = { |
|
133 /** |
|
134 * The object to be animated. |
|
135 * @attribute node |
|
136 * @type Node |
|
137 */ |
|
138 node: { |
|
139 setter: function(node) { |
|
140 node = Y.get(node); |
|
141 this._node = node; |
|
142 if (!node) { |
|
143 Y.log(node + ' is not a valid node', 'warn', 'Anim'); |
|
144 } |
|
145 return node; |
|
146 } |
|
147 }, |
|
148 |
|
149 /** |
|
150 * The length of the animation. Defaults to "1" (second). |
|
151 * @attribute duration |
|
152 * @type NUM |
|
153 */ |
|
154 duration: { |
|
155 value: 1 |
|
156 }, |
|
157 |
|
158 /** |
|
159 * The method that will provide values to the attribute(s) during the animation. |
|
160 * Defaults to "Easing.easeNone". |
|
161 * @attribute easing |
|
162 * @type Function |
|
163 */ |
|
164 easing: { |
|
165 value: Y.Anim.DEFAULT_EASING, |
|
166 |
|
167 setter: function(val) { |
|
168 if (typeof val === 'string' && Y.Easing) { |
|
169 return Y.Easing[val]; |
|
170 } |
|
171 } |
|
172 }, |
|
173 |
|
174 /** |
|
175 * The starting values for the animated properties. |
|
176 * Fields may be strings, numbers, or functions. |
|
177 * If a function is used, the return value becomes the from value. |
|
178 * If no from value is specified, the DEFAULT_GETTER will be used. |
|
179 * @attribute from |
|
180 * @type Object |
|
181 */ |
|
182 from: {}, |
|
183 |
|
184 /** |
|
185 * The ending values for the animated properties. |
|
186 * Fields may be strings, numbers, or functions. |
|
187 * @attribute to |
|
188 * @type Object |
|
189 */ |
|
190 to: {}, |
|
191 |
|
192 /** |
|
193 * Date stamp for the first frame of the animation. |
|
194 * @attribute startTime |
|
195 * @type Int |
|
196 * @default 0 |
|
197 * @readOnly |
|
198 */ |
|
199 startTime: { |
|
200 value: 0, |
|
201 readOnly: true |
|
202 }, |
|
203 |
|
204 /** |
|
205 * Current time the animation has been running. |
|
206 * @attribute elapsedTime |
|
207 * @type Int |
|
208 * @default 0 |
|
209 * @readOnly |
|
210 */ |
|
211 elapsedTime: { |
|
212 value: 0, |
|
213 readOnly: true |
|
214 }, |
|
215 |
|
216 /** |
|
217 * Whether or not the animation is currently running. |
|
218 * @attribute running |
|
219 * @type Boolean |
|
220 * @default false |
|
221 * @readOnly |
|
222 */ |
|
223 running: { |
|
224 getter: function() { |
|
225 return !!_running[Y.stamp(this)]; |
|
226 }, |
|
227 value: false, |
|
228 readOnly: true |
|
229 }, |
|
230 |
|
231 /** |
|
232 * The number of times the animation should run |
|
233 * @attribute iterations |
|
234 * @type Int |
|
235 * @default 1 |
|
236 */ |
|
237 iterations: { |
|
238 value: 1 |
|
239 }, |
|
240 |
|
241 /** |
|
242 * The number of iterations that have occurred. |
|
243 * Resets when an animation ends (reaches iteration count or stop() called). |
|
244 * @attribute iterationCount |
|
245 * @type Int |
|
246 * @default 0 |
|
247 * @readOnly |
|
248 */ |
|
249 iterationCount: { |
|
250 value: 0, |
|
251 readOnly: true |
|
252 }, |
|
253 |
|
254 /** |
|
255 * How iterations of the animation should behave. |
|
256 * Possible values are "normal" and "alternate". |
|
257 * Normal will repeat the animation, alternate will reverse on every other pass. |
|
258 * |
|
259 * @attribute direction |
|
260 * @type String |
|
261 * @default "normal" |
|
262 */ |
|
263 direction: { |
|
264 value: 'normal' // | alternate (fwd on odd, rev on even per spec) |
|
265 }, |
|
266 |
|
267 /** |
|
268 * Whether or not the animation is currently paused. |
|
269 * @attribute paused |
|
270 * @type Boolean |
|
271 * @default false |
|
272 * @readOnly |
|
273 */ |
|
274 paused: { |
|
275 readOnly: true, |
|
276 value: false |
|
277 }, |
|
278 |
|
279 /** |
|
280 * If true, animation begins from last frame |
|
281 * @attribute reverse |
|
282 * @type Boolean |
|
283 * @default false |
|
284 */ |
|
285 reverse: { |
|
286 value: false |
|
287 } |
|
288 |
|
289 |
|
290 }; |
|
291 |
|
292 /** |
|
293 * Runs all animation instances. |
|
294 * @method run |
|
295 * @static |
|
296 */ |
|
297 Y.Anim.run = function() { |
|
298 for (var i in _instances) { |
|
299 if (_instances[i].run) { |
|
300 _instances[i].run(); |
|
301 } |
|
302 } |
|
303 }; |
|
304 |
|
305 /** |
|
306 * Pauses all animation instances. |
|
307 * @method pause |
|
308 * @static |
|
309 */ |
|
310 Y.Anim.pause = function() { |
|
311 for (var i in _running) { // stop timer if nothing running |
|
312 if (_running[i].pause) { |
|
313 _running[i].pause(); |
|
314 } |
|
315 } |
|
316 Y.Anim._stopTimer(); |
|
317 }; |
|
318 |
|
319 /** |
|
320 * Stops all animation instances. |
|
321 * @method stop |
|
322 * @static |
|
323 */ |
|
324 Y.Anim.stop = function() { |
|
325 for (var i in _running) { // stop timer if nothing running |
|
326 if (_running[i].stop) { |
|
327 _running[i].stop(); |
|
328 } |
|
329 } |
|
330 Y.Anim._stopTimer(); |
|
331 }; |
|
332 |
|
333 Y.Anim._startTimer = function() { |
|
334 if (!_timer) { |
|
335 _timer = setInterval(Y.Anim._runFrame, 1); |
|
336 } |
|
337 }; |
|
338 |
|
339 Y.Anim._stopTimer = function() { |
|
340 clearInterval(_timer); |
|
341 _timer = 0; |
|
342 }; |
|
343 |
|
344 /** |
|
345 * Called per Interval to handle each animation frame. |
|
346 * @method _runFrame |
|
347 * @private |
|
348 * @static |
|
349 */ |
|
350 Y.Anim._runFrame = function() { |
|
351 var done = true; |
|
352 for (var anim in _running) { |
|
353 if (_running[anim]._runFrame) { |
|
354 done = false; |
|
355 _running[anim]._runFrame(); |
|
356 } |
|
357 } |
|
358 |
|
359 if (done) { |
|
360 Y.Anim._stopTimer(); |
|
361 } |
|
362 }; |
|
363 |
|
364 Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/; |
|
365 |
|
366 var proto = { |
|
367 /** |
|
368 * Starts or resumes an animation. |
|
369 * percent start time marker. |
|
370 * @method run |
|
371 * @chainable |
|
372 */ |
|
373 run: function() { |
|
374 if (!this.get(RUNNING)) { |
|
375 this._start(); |
|
376 } else if (this.get(PAUSED)) { |
|
377 this._resume(); |
|
378 } |
|
379 return this; |
|
380 }, |
|
381 |
|
382 /** |
|
383 * Pauses the animation and |
|
384 * freezes it in its current state and time. |
|
385 * Calling run() will continue where it left off. |
|
386 * @method pause |
|
387 * @chainable |
|
388 */ |
|
389 pause: function() { |
|
390 if (this.get(RUNNING)) { |
|
391 this._pause(); |
|
392 } |
|
393 return this; |
|
394 }, |
|
395 |
|
396 /** |
|
397 * Stops the animation and resets its time. |
|
398 * @method stop |
|
399 * @chainable |
|
400 */ |
|
401 stop: function(finish) { |
|
402 if (this.get(RUNNING) || this.get(PAUSED)) { |
|
403 this._end(finish); |
|
404 } |
|
405 return this; |
|
406 }, |
|
407 |
|
408 _added: false, |
|
409 |
|
410 _start: function() { |
|
411 this._set(START_TIME, new Date() - this.get(ELAPSED_TIME)); |
|
412 this._actualFrames = 0; |
|
413 if (!this.get(PAUSED)) { |
|
414 this._initAnimAttr(); |
|
415 } |
|
416 _running[Y.stamp(this)] = this; |
|
417 Y.Anim._startTimer(); |
|
418 |
|
419 this.fire(START); |
|
420 }, |
|
421 |
|
422 _pause: function() { |
|
423 this._set(START_TIME, null); |
|
424 this._set(PAUSED, true); |
|
425 delete _running[Y.stamp(this)]; |
|
426 |
|
427 /** |
|
428 * @event pause |
|
429 * @description fires when an animation is paused. |
|
430 * @param {Event} ev The pause event. |
|
431 * @type Event.Custom |
|
432 */ |
|
433 this.fire('pause'); |
|
434 }, |
|
435 |
|
436 _resume: function() { |
|
437 this._set(PAUSED, false); |
|
438 _running[Y.stamp(this)] = this; |
|
439 |
|
440 /** |
|
441 * @event resume |
|
442 * @description fires when an animation is resumed (run from pause). |
|
443 * @param {Event} ev The pause event. |
|
444 * @type Event.Custom |
|
445 */ |
|
446 this.fire('resume'); |
|
447 }, |
|
448 |
|
449 _end: function(finish) { |
|
450 this._set(START_TIME, null); |
|
451 this._set(ELAPSED_TIME, 0); |
|
452 this._set(PAUSED, false); |
|
453 |
|
454 delete _running[Y.stamp(this)]; |
|
455 this.fire(END, {elapsed: this.get(ELAPSED_TIME)}); |
|
456 }, |
|
457 |
|
458 _runFrame: function() { |
|
459 var attr = this._runtimeAttr, |
|
460 customAttr = Y.Anim.behaviors, |
|
461 easing = attr.easing, |
|
462 d = attr.duration, |
|
463 t = new Date() - this.get(START_TIME), |
|
464 reversed = this.get(REVERSE), |
|
465 done = (t >= d), |
|
466 lastFrame = d, |
|
467 attribute, |
|
468 setter; |
|
469 |
|
470 if (reversed) { |
|
471 t = d - t; |
|
472 done = (t <= 0); |
|
473 lastFrame = 0; |
|
474 } |
|
475 |
|
476 for (var i in attr) { |
|
477 if (attr[i].to) { |
|
478 attribute = attr[i]; |
|
479 setter = (i in customAttr && 'set' in customAttr[i]) ? |
|
480 customAttr[i].set : Y.Anim.DEFAULT_SETTER; |
|
481 |
|
482 if (!done) { |
|
483 setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit); |
|
484 } else { // ensure final frame value is set |
|
485 // TODO: handle keyframes |
|
486 setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit); |
|
487 } |
|
488 } |
|
489 } |
|
490 |
|
491 this._actualFrames += 1; |
|
492 this._set(ELAPSED_TIME, t); |
|
493 |
|
494 this.fire(TWEEN); |
|
495 if (done) { |
|
496 this._lastFrame(); |
|
497 } |
|
498 }, |
|
499 |
|
500 _lastFrame: function() { |
|
501 var iter = this.get('iterations'), |
|
502 iterCount = this.get(ITERATION_COUNT); |
|
503 |
|
504 iterCount += 1; |
|
505 if (iter === 'infinite' || iterCount < iter) { |
|
506 if (this.get('direction') === 'alternate') { |
|
507 this.set(REVERSE, !this.get(REVERSE)); // flip it |
|
508 } |
|
509 /** |
|
510 * @event iteration |
|
511 * @description fires when an animation begins an iteration. |
|
512 * @param {Event} ev The iteration event. |
|
513 * @type Event.Custom |
|
514 */ |
|
515 this.fire('iteration'); |
|
516 } else { |
|
517 iterCount = 0; |
|
518 this._end(); |
|
519 } |
|
520 |
|
521 this._set(START_TIME, new Date()); |
|
522 this._set(ITERATION_COUNT, iterCount); |
|
523 }, |
|
524 |
|
525 _initAnimAttr: function() { |
|
526 var from = this.get('from') || {}, |
|
527 to = this.get('to') || {}, |
|
528 dur = this.get('duration') * 1000, |
|
529 node = this.get(NODE), |
|
530 easing = this.get('easing') || {}, |
|
531 attr = {}, |
|
532 customAttr = Y.Anim.behaviors, |
|
533 unit, begin, end; |
|
534 |
|
535 Y.each(to, function(val, name) { |
|
536 if (typeof val === 'function') { |
|
537 val = val.call(this, node); |
|
538 } |
|
539 |
|
540 begin = from[name]; |
|
541 if (begin === undefined) { |
|
542 begin = (name in customAttr && 'get' in customAttr[name]) ? |
|
543 customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name); |
|
544 } else if (typeof begin === 'function') { |
|
545 begin = begin.call(this, node); |
|
546 } |
|
547 |
|
548 var mFrom = Y.Anim.RE_UNITS.exec(begin); |
|
549 var mTo = Y.Anim.RE_UNITS.exec(val); |
|
550 |
|
551 begin = mFrom ? mFrom[1] : begin; |
|
552 end = mTo ? mTo[1] : val; |
|
553 unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units |
|
554 |
|
555 if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) { |
|
556 unit = Y.Anim.DEFAULT_UNIT; |
|
557 } |
|
558 |
|
559 if (!begin || !end) { |
|
560 Y.error('invalid "from" or "to" for "' + name + '"', 'Anim'); |
|
561 return; |
|
562 } |
|
563 |
|
564 attr[name] = { |
|
565 from: begin, |
|
566 to: end, |
|
567 unit: unit |
|
568 }; |
|
569 |
|
570 attr.duration = dur; |
|
571 attr.easing = easing; |
|
572 |
|
573 }, this); |
|
574 |
|
575 this._runtimeAttr = attr; |
|
576 }, |
|
577 |
|
578 |
|
579 // TODO: move to computedStyle? (browsers dont agree on default computed offsets) |
|
580 _getOffset: function(attr) { |
|
581 var node = this._node, |
|
582 val = node.getComputedStyle(attr), |
|
583 get = (attr === 'left') ? 'getX': 'getY', |
|
584 set = (attr === 'left') ? 'setX': 'setY'; |
|
585 |
|
586 if (val === 'auto') { |
|
587 var position = node.getStyle('position'); |
|
588 if (position === 'absolute' || position === 'fixed') { |
|
589 val = node[get](); |
|
590 node[set](val); |
|
591 } else { |
|
592 val = 0; |
|
593 } |
|
594 } |
|
595 |
|
596 return val; |
|
597 } |
|
598 }; |
|
599 |
|
600 Y.extend(Y.Anim, Y.Base, proto); |
|
601 |
|
602 |
|
603 }, '3.0.0' ,{requires:['base-base', 'node-style']}); |
|
604 YUI.add('anim-color', function(Y) { |
|
605 |
|
606 /** |
|
607 * Adds support for color properties in <code>to</code> |
|
608 * and <code>from</code> attributes. |
|
609 * @module anim |
|
610 * @submodule anim-color |
|
611 */ |
|
612 |
|
613 var NUM = Number; |
|
614 |
|
615 Y.Anim.behaviors.color = { |
|
616 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
617 from = Y.Color.re_RGB.exec(Y.Color.toRGB(from)); |
|
618 to = Y.Color.re_RGB.exec(Y.Color.toRGB(to)); |
|
619 |
|
620 if (!from || from.length < 3 || !to || to.length < 3) { |
|
621 Y.error('invalid from or to passed to color behavior'); |
|
622 } |
|
623 |
|
624 anim._node.setStyle(att, 'rgb(' + [ |
|
625 Math.floor(fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration)), |
|
626 Math.floor(fn(elapsed, NUM(from[2]), NUM(to[2]) - NUM(from[2]), duration)), |
|
627 Math.floor(fn(elapsed, NUM(from[3]), NUM(to[3]) - NUM(from[3]), duration)) |
|
628 ].join(', ') + ')'); |
|
629 }, |
|
630 |
|
631 // TODO: default bgcolor const |
|
632 get: function(anim, att) { |
|
633 var val = anim._node.getComputedStyle(att); |
|
634 val = (val === 'transparent') ? 'rgb(255, 255, 255)' : val; |
|
635 return val; |
|
636 } |
|
637 }; |
|
638 |
|
639 Y.each(['backgroundColor', |
|
640 'borderColor', |
|
641 'borderTopColor', |
|
642 'borderRightColor', |
|
643 'borderBottomColor', |
|
644 'borderLeftColor'], |
|
645 function(v, i) { |
|
646 Y.Anim.behaviors[v] = Y.Anim.behaviors.color; |
|
647 } |
|
648 ); |
|
649 |
|
650 |
|
651 }, '3.0.0' ,{requires:['anim-base']}); |
|
652 YUI.add('anim-curve', function(Y) { |
|
653 |
|
654 /** |
|
655 * Adds support for the <code>curve</code> property for the <code>to</code> |
|
656 * attribute. A curve is zero or more control points and an end point. |
|
657 * @module anim |
|
658 * @submodule anim-curve |
|
659 */ |
|
660 |
|
661 Y.Anim.behaviors.curve = { |
|
662 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
663 from = from.slice.call(from); |
|
664 to = to.slice.call(to); |
|
665 var t = fn(elapsed, 0, 100, duration) / 100; |
|
666 to.unshift(from); |
|
667 anim._node.setXY(Y.Anim.getBezier(to, t)); |
|
668 }, |
|
669 |
|
670 get: function(anim, att) { |
|
671 return anim._node.getXY(); |
|
672 } |
|
673 }; |
|
674 |
|
675 /** |
|
676 * Get the current position of the animated element based on t. |
|
677 * Each point is an array of "x" and "y" values (0 = x, 1 = y) |
|
678 * At least 2 points are required (start and end). |
|
679 * First point is start. Last point is end. |
|
680 * Additional control points are optional. |
|
681 * @for Anim |
|
682 * @method getBezier |
|
683 * @static |
|
684 * @param {Array} points An array containing Bezier points |
|
685 * @param {Number} t A number between 0 and 1 which is the basis for determining current position |
|
686 * @return {Array} An array containing int x and y member data |
|
687 */ |
|
688 Y.Anim.getBezier = function(points, t) { |
|
689 var n = points.length; |
|
690 var tmp = []; |
|
691 |
|
692 for (var i = 0; i < n; ++i){ |
|
693 tmp[i] = [points[i][0], points[i][1]]; // save input |
|
694 } |
|
695 |
|
696 for (var j = 1; j < n; ++j) { |
|
697 for (i = 0; i < n - j; ++i) { |
|
698 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; |
|
699 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; |
|
700 } |
|
701 } |
|
702 |
|
703 return [ tmp[0][0], tmp[0][1] ]; |
|
704 |
|
705 }; |
|
706 |
|
707 |
|
708 }, '3.0.0' ,{requires:['anim-xy']}); |
|
709 YUI.add('anim-easing', function(Y) { |
|
710 |
|
711 /* |
|
712 TERMS OF USE - EASING EQUATIONS |
|
713 Open source under the BSD License. |
|
714 Copyright 2001 Robert Penner All rights reserved. |
|
715 |
|
716 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
717 |
|
718 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
719 * 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. |
|
720 * 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. |
|
721 |
|
722 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. |
|
723 */ |
|
724 |
|
725 /** |
|
726 * The easing module provides methods for customizing |
|
727 * how an animation behaves during each run. |
|
728 * @class Easing |
|
729 * @module anim |
|
730 * @submodule anim-easing |
|
731 */ |
|
732 |
|
733 Y.Easing = { |
|
734 |
|
735 /** |
|
736 * Uniform speed between points. |
|
737 * @for Easing |
|
738 * @method easeNone |
|
739 * @param {Number} t Time value used to compute current value |
|
740 * @param {Number} b Starting value |
|
741 * @param {Number} c Delta between start and end values |
|
742 * @param {Number} d Total length of animation |
|
743 * @return {Number} The computed value for the current animation frame |
|
744 */ |
|
745 easeNone: function (t, b, c, d) { |
|
746 return c*t/d + b; |
|
747 }, |
|
748 |
|
749 /** |
|
750 * Begins slowly and accelerates towards end. (quadratic) |
|
751 * @method easeIn |
|
752 * @param {Number} t Time value used to compute current value |
|
753 * @param {Number} b Starting value |
|
754 * @param {Number} c Delta between start and end values |
|
755 * @param {Number} d Total length of animation |
|
756 * @return {Number} The computed value for the current animation frame |
|
757 */ |
|
758 easeIn: function (t, b, c, d) { |
|
759 return c*(t/=d)*t + b; |
|
760 }, |
|
761 |
|
762 /** |
|
763 * Begins quickly and decelerates towards end. (quadratic) |
|
764 * @method easeOut |
|
765 * @param {Number} t Time value used to compute current value |
|
766 * @param {Number} b Starting value |
|
767 * @param {Number} c Delta between start and end values |
|
768 * @param {Number} d Total length of animation |
|
769 * @return {Number} The computed value for the current animation frame |
|
770 */ |
|
771 easeOut: function (t, b, c, d) { |
|
772 return -c *(t/=d)*(t-2) + b; |
|
773 }, |
|
774 |
|
775 /** |
|
776 * Begins slowly and decelerates towards end. (quadratic) |
|
777 * @method easeBoth |
|
778 * @param {Number} t Time value used to compute current value |
|
779 * @param {Number} b Starting value |
|
780 * @param {Number} c Delta between start and end values |
|
781 * @param {Number} d Total length of animation |
|
782 * @return {Number} The computed value for the current animation frame |
|
783 */ |
|
784 easeBoth: function (t, b, c, d) { |
|
785 if ((t/=d/2) < 1) { |
|
786 return c/2*t*t + b; |
|
787 } |
|
788 |
|
789 return -c/2 * ((--t)*(t-2) - 1) + b; |
|
790 }, |
|
791 |
|
792 /** |
|
793 * Begins slowly and accelerates towards end. (quartic) |
|
794 * @method easeInStrong |
|
795 * @param {Number} t Time value used to compute current value |
|
796 * @param {Number} b Starting value |
|
797 * @param {Number} c Delta between start and end values |
|
798 * @param {Number} d Total length of animation |
|
799 * @return {Number} The computed value for the current animation frame |
|
800 */ |
|
801 easeInStrong: function (t, b, c, d) { |
|
802 return c*(t/=d)*t*t*t + b; |
|
803 }, |
|
804 |
|
805 /** |
|
806 * Begins quickly and decelerates towards end. (quartic) |
|
807 * @method easeOutStrong |
|
808 * @param {Number} t Time value used to compute current value |
|
809 * @param {Number} b Starting value |
|
810 * @param {Number} c Delta between start and end values |
|
811 * @param {Number} d Total length of animation |
|
812 * @return {Number} The computed value for the current animation frame |
|
813 */ |
|
814 easeOutStrong: function (t, b, c, d) { |
|
815 return -c * ((t=t/d-1)*t*t*t - 1) + b; |
|
816 }, |
|
817 |
|
818 /** |
|
819 * Begins slowly and decelerates towards end. (quartic) |
|
820 * @method easeBothStrong |
|
821 * @param {Number} t Time value used to compute current value |
|
822 * @param {Number} b Starting value |
|
823 * @param {Number} c Delta between start and end values |
|
824 * @param {Number} d Total length of animation |
|
825 * @return {Number} The computed value for the current animation frame |
|
826 */ |
|
827 easeBothStrong: function (t, b, c, d) { |
|
828 if ((t/=d/2) < 1) { |
|
829 return c/2*t*t*t*t + b; |
|
830 } |
|
831 |
|
832 return -c/2 * ((t-=2)*t*t*t - 2) + b; |
|
833 }, |
|
834 |
|
835 /** |
|
836 * Snap in elastic effect. |
|
837 * @method elasticIn |
|
838 * @param {Number} t Time value used to compute current value |
|
839 * @param {Number} b Starting value |
|
840 * @param {Number} c Delta between start and end values |
|
841 * @param {Number} d Total length of animation |
|
842 * @param {Number} a Amplitude (optional) |
|
843 * @param {Number} p Period (optional) |
|
844 * @return {Number} The computed value for the current animation frame |
|
845 */ |
|
846 |
|
847 elasticIn: function (t, b, c, d, a, p) { |
|
848 var s; |
|
849 if (t === 0) { |
|
850 return b; |
|
851 } |
|
852 if ( (t /= d) === 1 ) { |
|
853 return b+c; |
|
854 } |
|
855 if (!p) { |
|
856 p = d* 0.3; |
|
857 } |
|
858 |
|
859 if (!a || a < Math.abs(c)) { |
|
860 a = c; |
|
861 s = p/4; |
|
862 } |
|
863 else { |
|
864 s = p/(2*Math.PI) * Math.asin (c/a); |
|
865 } |
|
866 |
|
867 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; |
|
868 }, |
|
869 |
|
870 /** |
|
871 * Snap out elastic effect. |
|
872 * @method elasticOut |
|
873 * @param {Number} t Time value used to compute current value |
|
874 * @param {Number} b Starting value |
|
875 * @param {Number} c Delta between start and end values |
|
876 * @param {Number} d Total length of animation |
|
877 * @param {Number} a Amplitude (optional) |
|
878 * @param {Number} p Period (optional) |
|
879 * @return {Number} The computed value for the current animation frame |
|
880 */ |
|
881 elasticOut: function (t, b, c, d, a, p) { |
|
882 var s; |
|
883 if (t === 0) { |
|
884 return b; |
|
885 } |
|
886 if ( (t /= d) === 1 ) { |
|
887 return b+c; |
|
888 } |
|
889 if (!p) { |
|
890 p=d * 0.3; |
|
891 } |
|
892 |
|
893 if (!a || a < Math.abs(c)) { |
|
894 a = c; |
|
895 s = p / 4; |
|
896 } |
|
897 else { |
|
898 s = p/(2*Math.PI) * Math.asin (c/a); |
|
899 } |
|
900 |
|
901 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; |
|
902 }, |
|
903 |
|
904 /** |
|
905 * Snap both elastic effect. |
|
906 * @method elasticBoth |
|
907 * @param {Number} t Time value used to compute current value |
|
908 * @param {Number} b Starting value |
|
909 * @param {Number} c Delta between start and end values |
|
910 * @param {Number} d Total length of animation |
|
911 * @param {Number} a Amplitude (optional) |
|
912 * @param {Number} p Period (optional) |
|
913 * @return {Number} The computed value for the current animation frame |
|
914 */ |
|
915 elasticBoth: function (t, b, c, d, a, p) { |
|
916 var s; |
|
917 if (t === 0) { |
|
918 return b; |
|
919 } |
|
920 |
|
921 if ( (t /= d/2) === 2 ) { |
|
922 return b+c; |
|
923 } |
|
924 |
|
925 if (!p) { |
|
926 p = d*(0.3*1.5); |
|
927 } |
|
928 |
|
929 if ( !a || a < Math.abs(c) ) { |
|
930 a = c; |
|
931 s = p/4; |
|
932 } |
|
933 else { |
|
934 s = p/(2*Math.PI) * Math.asin (c/a); |
|
935 } |
|
936 |
|
937 if (t < 1) { |
|
938 return -0.5*(a*Math.pow(2,10*(t-=1)) * |
|
939 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; |
|
940 } |
|
941 return a*Math.pow(2,-10*(t-=1)) * |
|
942 Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; |
|
943 }, |
|
944 |
|
945 |
|
946 /** |
|
947 * Backtracks slightly, then reverses direction and moves to end. |
|
948 * @method backIn |
|
949 * @param {Number} t Time value used to compute current value |
|
950 * @param {Number} b Starting value |
|
951 * @param {Number} c Delta between start and end values |
|
952 * @param {Number} d Total length of animation |
|
953 * @param {Number} s Overshoot (optional) |
|
954 * @return {Number} The computed value for the current animation frame |
|
955 */ |
|
956 backIn: function (t, b, c, d, s) { |
|
957 if (s === undefined) { |
|
958 s = 1.70158; |
|
959 } |
|
960 if (t === d) { |
|
961 t -= 0.001; |
|
962 } |
|
963 return c*(t/=d)*t*((s+1)*t - s) + b; |
|
964 }, |
|
965 |
|
966 /** |
|
967 * Overshoots end, then reverses and comes back to end. |
|
968 * @method backOut |
|
969 * @param {Number} t Time value used to compute current value |
|
970 * @param {Number} b Starting value |
|
971 * @param {Number} c Delta between start and end values |
|
972 * @param {Number} d Total length of animation |
|
973 * @param {Number} s Overshoot (optional) |
|
974 * @return {Number} The computed value for the current animation frame |
|
975 */ |
|
976 backOut: function (t, b, c, d, s) { |
|
977 if (typeof s === 'undefined') { |
|
978 s = 1.70158; |
|
979 } |
|
980 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; |
|
981 }, |
|
982 |
|
983 /** |
|
984 * Backtracks slightly, then reverses direction, overshoots end, |
|
985 * then reverses and comes back to end. |
|
986 * @method backBoth |
|
987 * @param {Number} t Time value used to compute current value |
|
988 * @param {Number} b Starting value |
|
989 * @param {Number} c Delta between start and end values |
|
990 * @param {Number} d Total length of animation |
|
991 * @param {Number} s Overshoot (optional) |
|
992 * @return {Number} The computed value for the current animation frame |
|
993 */ |
|
994 backBoth: function (t, b, c, d, s) { |
|
995 if (typeof s === 'undefined') { |
|
996 s = 1.70158; |
|
997 } |
|
998 |
|
999 if ((t /= d/2 ) < 1) { |
|
1000 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; |
|
1001 } |
|
1002 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; |
|
1003 }, |
|
1004 |
|
1005 /** |
|
1006 * Bounce off of start. |
|
1007 * @method bounceIn |
|
1008 * @param {Number} t Time value used to compute current value |
|
1009 * @param {Number} b Starting value |
|
1010 * @param {Number} c Delta between start and end values |
|
1011 * @param {Number} d Total length of animation |
|
1012 * @return {Number} The computed value for the current animation frame |
|
1013 */ |
|
1014 bounceIn: function (t, b, c, d) { |
|
1015 return c - Y.Easing.bounceOut(d-t, 0, c, d) + b; |
|
1016 }, |
|
1017 |
|
1018 /** |
|
1019 * Bounces off end. |
|
1020 * @method bounceOut |
|
1021 * @param {Number} t Time value used to compute current value |
|
1022 * @param {Number} b Starting value |
|
1023 * @param {Number} c Delta between start and end values |
|
1024 * @param {Number} d Total length of animation |
|
1025 * @return {Number} The computed value for the current animation frame |
|
1026 */ |
|
1027 bounceOut: function (t, b, c, d) { |
|
1028 if ((t/=d) < (1/2.75)) { |
|
1029 return c*(7.5625*t*t) + b; |
|
1030 } else if (t < (2/2.75)) { |
|
1031 return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; |
|
1032 } else if (t < (2.5/2.75)) { |
|
1033 return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; |
|
1034 } |
|
1035 return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; |
|
1036 }, |
|
1037 |
|
1038 /** |
|
1039 * Bounces off start and end. |
|
1040 * @method bounceBoth |
|
1041 * @param {Number} t Time value used to compute current value |
|
1042 * @param {Number} b Starting value |
|
1043 * @param {Number} c Delta between start and end values |
|
1044 * @param {Number} d Total length of animation |
|
1045 * @return {Number} The computed value for the current animation frame |
|
1046 */ |
|
1047 bounceBoth: function (t, b, c, d) { |
|
1048 if (t < d/2) { |
|
1049 return Y.Easing.bounceIn(t * 2, 0, c, d) * 0.5 + b; |
|
1050 } |
|
1051 return Y.Easing.bounceOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; |
|
1052 } |
|
1053 }; |
|
1054 |
|
1055 |
|
1056 }, '3.0.0' ,{requires:['anim-base']}); |
|
1057 YUI.add('anim-node-plugin', function(Y) { |
|
1058 |
|
1059 /** |
|
1060 * Binds an Anim instance to a Node instance |
|
1061 * @module anim |
|
1062 * @class Plugin.NodeFX |
|
1063 * @extends Base |
|
1064 * @submodule anim-node-plugin |
|
1065 */ |
|
1066 |
|
1067 var NodeFX = function(config) { |
|
1068 config = (config) ? Y.merge(config) : {}; |
|
1069 config.node = config.host; |
|
1070 NodeFX.superclass.constructor.apply(this, arguments); |
|
1071 }; |
|
1072 |
|
1073 NodeFX.NAME = "nodefx"; |
|
1074 NodeFX.NS = "fx"; |
|
1075 |
|
1076 Y.extend(NodeFX, Y.Anim); |
|
1077 |
|
1078 Y.namespace('Plugin'); |
|
1079 Y.Plugin.NodeFX = NodeFX; |
|
1080 |
|
1081 |
|
1082 }, '3.0.0' ,{requires:['node-pluginhost', 'anim-base']}); |
|
1083 YUI.add('anim-scroll', function(Y) { |
|
1084 |
|
1085 /** |
|
1086 * Adds support for the <code>scroll</code> property in <code>to</code> |
|
1087 * and <code>from</code> attributes. |
|
1088 * @module anim |
|
1089 * @submodule anim-scroll |
|
1090 */ |
|
1091 |
|
1092 var NUM = Number; |
|
1093 |
|
1094 //TODO: deprecate for scrollTop/Left properties? |
|
1095 Y.Anim.behaviors.scroll = { |
|
1096 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
1097 var |
|
1098 node = anim._node, |
|
1099 val = ([ |
|
1100 fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration), |
|
1101 fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration) |
|
1102 ]); |
|
1103 |
|
1104 if (val[0]) { |
|
1105 node.set('scrollLeft', val[0]); |
|
1106 } |
|
1107 |
|
1108 if (val[1]) { |
|
1109 node.set('scrollTop', val[1]); |
|
1110 } |
|
1111 }, |
|
1112 get: function(anim) { |
|
1113 var node = anim._node; |
|
1114 return [node.get('scrollLeft'), node.get('scrollTop')]; |
|
1115 } |
|
1116 }; |
|
1117 |
|
1118 |
|
1119 |
|
1120 }, '3.0.0' ,{requires:['anim-base']}); |
|
1121 YUI.add('anim-xy', function(Y) { |
|
1122 |
|
1123 /** |
|
1124 * Adds support for the <code>xy</code> property in <code>from</code> and |
|
1125 * <code>to</code> attributes. |
|
1126 * @module anim |
|
1127 * @submodule anim-xy |
|
1128 */ |
|
1129 |
|
1130 var NUM = Number; |
|
1131 |
|
1132 Y.Anim.behaviors.xy = { |
|
1133 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
1134 anim._node.setXY([ |
|
1135 fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration), |
|
1136 fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration) |
|
1137 ]); |
|
1138 }, |
|
1139 get: function(anim) { |
|
1140 return anim._node.getXY(); |
|
1141 } |
|
1142 }; |
|
1143 |
|
1144 |
|
1145 |
|
1146 }, '3.0.0' ,{requires:['anim-base', 'node-screen']}); |
|
1147 |
|
1148 |
|
1149 YUI.add('anim', function(Y){}, '3.0.0' ,{use:['anim-base', 'anim-color', 'anim-curve', 'anim-easing', 'anim-node-plugin', 'anim-scroll', 'anim-xy'], skinnable:false}); |
|
1150 |