|
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.0b1 |
|
6 build: 1163 |
|
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 running |
|
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 |
|
604 }, '3.0.0b1' ,{requires:['base', 'node']}); |
|
605 |
|
606 YUI.add('anim-color', function(Y) { |
|
607 |
|
608 /** |
|
609 * Adds support for color properties in <code>to</code> |
|
610 * and <code>from</code> attributes. |
|
611 * @module anim |
|
612 * @submodule anim-color |
|
613 */ |
|
614 |
|
615 var NUM = Number; |
|
616 |
|
617 Y.Anim.behaviors.color = { |
|
618 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
619 from = Y.Color.re_RGB.exec(Y.Color.toRGB(from)); |
|
620 to = Y.Color.re_RGB.exec(Y.Color.toRGB(to)); |
|
621 |
|
622 if (!from || from.length < 3 || !to || to.length < 3) { |
|
623 Y.error('invalid from or to passed to color behavior'); |
|
624 } |
|
625 |
|
626 anim._node.setStyle(att, 'rgb(' + [ |
|
627 Math.floor(fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration)), |
|
628 Math.floor(fn(elapsed, NUM(from[2]), NUM(to[2]) - NUM(from[2]), duration)), |
|
629 Math.floor(fn(elapsed, NUM(from[3]), NUM(to[3]) - NUM(from[3]), duration)) |
|
630 ].join(', ') + ')'); |
|
631 }, |
|
632 |
|
633 // TODO: default bgcolor const |
|
634 get: function(anim, att) { |
|
635 var val = anim._node.getComputedStyle(att); |
|
636 val = (val === 'transparent') ? 'rgb(255, 255, 255)' : val; |
|
637 return val; |
|
638 } |
|
639 }; |
|
640 |
|
641 Y.each(['backgroundColor', |
|
642 'borderColor', |
|
643 'borderTopColor', |
|
644 'borderRightColor', |
|
645 'borderBottomColor', |
|
646 'borderLeftColor'], |
|
647 function(v, i) { |
|
648 Y.Anim.behaviors[v] = Y.Anim.behaviors.color; |
|
649 } |
|
650 ); |
|
651 |
|
652 |
|
653 |
|
654 }, '3.0.0b1' ,{requires:['anim-base', 'node-style']}); |
|
655 |
|
656 YUI.add('anim-curve', function(Y) { |
|
657 |
|
658 /** |
|
659 * Adds support for the <code>curve</code> property for the <code>to</code> |
|
660 * attribute. A curve is zero or more control points and an end point. |
|
661 * @module anim |
|
662 * @submodule anim-curve |
|
663 */ |
|
664 |
|
665 Y.Anim.behaviors.curve = { |
|
666 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
667 from = from.slice.call(from); |
|
668 to = to.slice.call(to); |
|
669 var t = fn(elapsed, 0, 100, duration) / 100; |
|
670 to.unshift(from); |
|
671 anim._node.setXY(Y.Anim.getBezier(to, t)); |
|
672 }, |
|
673 |
|
674 get: function(anim, att) { |
|
675 return anim._node.getXY(); |
|
676 } |
|
677 }; |
|
678 |
|
679 /** |
|
680 * Get the current position of the animated element based on t. |
|
681 * Each point is an array of "x" and "y" values (0 = x, 1 = y) |
|
682 * At least 2 points are required (start and end). |
|
683 * First point is start. Last point is end. |
|
684 * Additional control points are optional. |
|
685 * @for Anim |
|
686 * @method getBezier |
|
687 * @static |
|
688 * @param {Array} points An array containing Bezier points |
|
689 * @param {Number} t A number between 0 and 1 which is the basis for determining current position |
|
690 * @return {Array} An array containing int x and y member data |
|
691 */ |
|
692 Y.Anim.getBezier = function(points, t) { |
|
693 var n = points.length; |
|
694 var tmp = []; |
|
695 |
|
696 for (var i = 0; i < n; ++i){ |
|
697 tmp[i] = [points[i][0], points[i][1]]; // save input |
|
698 } |
|
699 |
|
700 for (var j = 1; j < n; ++j) { |
|
701 for (i = 0; i < n - j; ++i) { |
|
702 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; |
|
703 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; |
|
704 } |
|
705 } |
|
706 |
|
707 return [ tmp[0][0], tmp[0][1] ]; |
|
708 |
|
709 }; |
|
710 |
|
711 |
|
712 |
|
713 }, '3.0.0b1' ,{requires:['anim-base', 'node-screen']}); |
|
714 |
|
715 YUI.add('anim-easing', function(Y) { |
|
716 |
|
717 /* |
|
718 TERMS OF USE - EASING EQUATIONS |
|
719 Open source under the BSD License. |
|
720 Copyright 2001 Robert Penner All rights reserved. |
|
721 |
|
722 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|
723 |
|
724 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|
725 * 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. |
|
726 * 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. |
|
727 |
|
728 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. |
|
729 */ |
|
730 |
|
731 /** |
|
732 * The easing module provides methods for customizing |
|
733 * how an animation behaves during each run. |
|
734 * @class Easing |
|
735 * @module anim |
|
736 * @submodule anim-easing |
|
737 */ |
|
738 |
|
739 Y.Easing = { |
|
740 |
|
741 /** |
|
742 * Uniform speed between points. |
|
743 * @for Easing |
|
744 * @method easeNone |
|
745 * @param {Number} t Time value used to compute current value |
|
746 * @param {Number} b Starting value |
|
747 * @param {Number} c Delta between start and end values |
|
748 * @param {Number} d Total length of animation |
|
749 * @return {Number} The computed value for the current animation frame |
|
750 */ |
|
751 easeNone: function (t, b, c, d) { |
|
752 return c*t/d + b; |
|
753 }, |
|
754 |
|
755 /** |
|
756 * Begins slowly and accelerates towards end. (quadratic) |
|
757 * @method easeIn |
|
758 * @param {Number} t Time value used to compute current value |
|
759 * @param {Number} b Starting value |
|
760 * @param {Number} c Delta between start and end values |
|
761 * @param {Number} d Total length of animation |
|
762 * @return {Number} The computed value for the current animation frame |
|
763 */ |
|
764 easeIn: function (t, b, c, d) { |
|
765 return c*(t/=d)*t + b; |
|
766 }, |
|
767 |
|
768 /** |
|
769 * Begins quickly and decelerates towards end. (quadratic) |
|
770 * @method easeOut |
|
771 * @param {Number} t Time value used to compute current value |
|
772 * @param {Number} b Starting value |
|
773 * @param {Number} c Delta between start and end values |
|
774 * @param {Number} d Total length of animation |
|
775 * @return {Number} The computed value for the current animation frame |
|
776 */ |
|
777 easeOut: function (t, b, c, d) { |
|
778 return -c *(t/=d)*(t-2) + b; |
|
779 }, |
|
780 |
|
781 /** |
|
782 * Begins slowly and decelerates towards end. (quadratic) |
|
783 * @method easeBoth |
|
784 * @param {Number} t Time value used to compute current value |
|
785 * @param {Number} b Starting value |
|
786 * @param {Number} c Delta between start and end values |
|
787 * @param {Number} d Total length of animation |
|
788 * @return {Number} The computed value for the current animation frame |
|
789 */ |
|
790 easeBoth: function (t, b, c, d) { |
|
791 if ((t/=d/2) < 1) { |
|
792 return c/2*t*t + b; |
|
793 } |
|
794 |
|
795 return -c/2 * ((--t)*(t-2) - 1) + b; |
|
796 }, |
|
797 |
|
798 /** |
|
799 * Begins slowly and accelerates towards end. (quartic) |
|
800 * @method easeInStrong |
|
801 * @param {Number} t Time value used to compute current value |
|
802 * @param {Number} b Starting value |
|
803 * @param {Number} c Delta between start and end values |
|
804 * @param {Number} d Total length of animation |
|
805 * @return {Number} The computed value for the current animation frame |
|
806 */ |
|
807 easeInStrong: function (t, b, c, d) { |
|
808 return c*(t/=d)*t*t*t + b; |
|
809 }, |
|
810 |
|
811 /** |
|
812 * Begins quickly and decelerates towards end. (quartic) |
|
813 * @method easeOutStrong |
|
814 * @param {Number} t Time value used to compute current value |
|
815 * @param {Number} b Starting value |
|
816 * @param {Number} c Delta between start and end values |
|
817 * @param {Number} d Total length of animation |
|
818 * @return {Number} The computed value for the current animation frame |
|
819 */ |
|
820 easeOutStrong: function (t, b, c, d) { |
|
821 return -c * ((t=t/d-1)*t*t*t - 1) + b; |
|
822 }, |
|
823 |
|
824 /** |
|
825 * Begins slowly and decelerates towards end. (quartic) |
|
826 * @method easeBothStrong |
|
827 * @param {Number} t Time value used to compute current value |
|
828 * @param {Number} b Starting value |
|
829 * @param {Number} c Delta between start and end values |
|
830 * @param {Number} d Total length of animation |
|
831 * @return {Number} The computed value for the current animation frame |
|
832 */ |
|
833 easeBothStrong: function (t, b, c, d) { |
|
834 if ((t/=d/2) < 1) { |
|
835 return c/2*t*t*t*t + b; |
|
836 } |
|
837 |
|
838 return -c/2 * ((t-=2)*t*t*t - 2) + b; |
|
839 }, |
|
840 |
|
841 /** |
|
842 * Snap in elastic effect. |
|
843 * @method elasticIn |
|
844 * @param {Number} t Time value used to compute current value |
|
845 * @param {Number} b Starting value |
|
846 * @param {Number} c Delta between start and end values |
|
847 * @param {Number} d Total length of animation |
|
848 * @param {Number} a Amplitude (optional) |
|
849 * @param {Number} p Period (optional) |
|
850 * @return {Number} The computed value for the current animation frame |
|
851 */ |
|
852 |
|
853 elasticIn: function (t, b, c, d, a, p) { |
|
854 var s; |
|
855 if (t === 0) { |
|
856 return b; |
|
857 } |
|
858 if ( (t /= d) === 1 ) { |
|
859 return b+c; |
|
860 } |
|
861 if (!p) { |
|
862 p = d* 0.3; |
|
863 } |
|
864 |
|
865 if (!a || a < Math.abs(c)) { |
|
866 a = c; |
|
867 s = p/4; |
|
868 } |
|
869 else { |
|
870 s = p/(2*Math.PI) * Math.asin (c/a); |
|
871 } |
|
872 |
|
873 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; |
|
874 }, |
|
875 |
|
876 /** |
|
877 * Snap out elastic effect. |
|
878 * @method elasticOut |
|
879 * @param {Number} t Time value used to compute current value |
|
880 * @param {Number} b Starting value |
|
881 * @param {Number} c Delta between start and end values |
|
882 * @param {Number} d Total length of animation |
|
883 * @param {Number} a Amplitude (optional) |
|
884 * @param {Number} p Period (optional) |
|
885 * @return {Number} The computed value for the current animation frame |
|
886 */ |
|
887 elasticOut: function (t, b, c, d, a, p) { |
|
888 var s; |
|
889 if (t === 0) { |
|
890 return b; |
|
891 } |
|
892 if ( (t /= d) === 1 ) { |
|
893 return b+c; |
|
894 } |
|
895 if (!p) { |
|
896 p=d * 0.3; |
|
897 } |
|
898 |
|
899 if (!a || a < Math.abs(c)) { |
|
900 a = c; |
|
901 s = p / 4; |
|
902 } |
|
903 else { |
|
904 s = p/(2*Math.PI) * Math.asin (c/a); |
|
905 } |
|
906 |
|
907 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; |
|
908 }, |
|
909 |
|
910 /** |
|
911 * Snap both elastic effect. |
|
912 * @method elasticBoth |
|
913 * @param {Number} t Time value used to compute current value |
|
914 * @param {Number} b Starting value |
|
915 * @param {Number} c Delta between start and end values |
|
916 * @param {Number} d Total length of animation |
|
917 * @param {Number} a Amplitude (optional) |
|
918 * @param {Number} p Period (optional) |
|
919 * @return {Number} The computed value for the current animation frame |
|
920 */ |
|
921 elasticBoth: function (t, b, c, d, a, p) { |
|
922 var s; |
|
923 if (t === 0) { |
|
924 return b; |
|
925 } |
|
926 |
|
927 if ( (t /= d/2) === 2 ) { |
|
928 return b+c; |
|
929 } |
|
930 |
|
931 if (!p) { |
|
932 p = d*(0.3*1.5); |
|
933 } |
|
934 |
|
935 if ( !a || a < Math.abs(c) ) { |
|
936 a = c; |
|
937 s = p/4; |
|
938 } |
|
939 else { |
|
940 s = p/(2*Math.PI) * Math.asin (c/a); |
|
941 } |
|
942 |
|
943 if (t < 1) { |
|
944 return -0.5*(a*Math.pow(2,10*(t-=1)) * |
|
945 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; |
|
946 } |
|
947 return a*Math.pow(2,-10*(t-=1)) * |
|
948 Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; |
|
949 }, |
|
950 |
|
951 |
|
952 /** |
|
953 * Backtracks slightly, then reverses direction and moves to end. |
|
954 * @method backIn |
|
955 * @param {Number} t Time value used to compute current value |
|
956 * @param {Number} b Starting value |
|
957 * @param {Number} c Delta between start and end values |
|
958 * @param {Number} d Total length of animation |
|
959 * @param {Number} s Overshoot (optional) |
|
960 * @return {Number} The computed value for the current animation frame |
|
961 */ |
|
962 backIn: function (t, b, c, d, s) { |
|
963 if (s === undefined) { |
|
964 s = 1.70158; |
|
965 } |
|
966 if (t === d) { |
|
967 t -= 0.001; |
|
968 } |
|
969 return c*(t/=d)*t*((s+1)*t - s) + b; |
|
970 }, |
|
971 |
|
972 /** |
|
973 * Overshoots end, then reverses and comes back to end. |
|
974 * @method backOut |
|
975 * @param {Number} t Time value used to compute current value |
|
976 * @param {Number} b Starting value |
|
977 * @param {Number} c Delta between start and end values |
|
978 * @param {Number} d Total length of animation |
|
979 * @param {Number} s Overshoot (optional) |
|
980 * @return {Number} The computed value for the current animation frame |
|
981 */ |
|
982 backOut: function (t, b, c, d, s) { |
|
983 if (typeof s === 'undefined') { |
|
984 s = 1.70158; |
|
985 } |
|
986 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; |
|
987 }, |
|
988 |
|
989 /** |
|
990 * Backtracks slightly, then reverses direction, overshoots end, |
|
991 * then reverses and comes back to end. |
|
992 * @method backBoth |
|
993 * @param {Number} t Time value used to compute current value |
|
994 * @param {Number} b Starting value |
|
995 * @param {Number} c Delta between start and end values |
|
996 * @param {Number} d Total length of animation |
|
997 * @param {Number} s Overshoot (optional) |
|
998 * @return {Number} The computed value for the current animation frame |
|
999 */ |
|
1000 backBoth: function (t, b, c, d, s) { |
|
1001 if (typeof s === 'undefined') { |
|
1002 s = 1.70158; |
|
1003 } |
|
1004 |
|
1005 if ((t /= d/2 ) < 1) { |
|
1006 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; |
|
1007 } |
|
1008 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; |
|
1009 }, |
|
1010 |
|
1011 /** |
|
1012 * Bounce off of start. |
|
1013 * @method bounceIn |
|
1014 * @param {Number} t Time value used to compute current value |
|
1015 * @param {Number} b Starting value |
|
1016 * @param {Number} c Delta between start and end values |
|
1017 * @param {Number} d Total length of animation |
|
1018 * @return {Number} The computed value for the current animation frame |
|
1019 */ |
|
1020 bounceIn: function (t, b, c, d) { |
|
1021 return c - Y.Easing.bounceOut(d-t, 0, c, d) + b; |
|
1022 }, |
|
1023 |
|
1024 /** |
|
1025 * Bounces off end. |
|
1026 * @method bounceOut |
|
1027 * @param {Number} t Time value used to compute current value |
|
1028 * @param {Number} b Starting value |
|
1029 * @param {Number} c Delta between start and end values |
|
1030 * @param {Number} d Total length of animation |
|
1031 * @return {Number} The computed value for the current animation frame |
|
1032 */ |
|
1033 bounceOut: function (t, b, c, d) { |
|
1034 if ((t/=d) < (1/2.75)) { |
|
1035 return c*(7.5625*t*t) + b; |
|
1036 } else if (t < (2/2.75)) { |
|
1037 return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; |
|
1038 } else if (t < (2.5/2.75)) { |
|
1039 return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; |
|
1040 } |
|
1041 return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; |
|
1042 }, |
|
1043 |
|
1044 /** |
|
1045 * Bounces off start and end. |
|
1046 * @method bounceBoth |
|
1047 * @param {Number} t Time value used to compute current value |
|
1048 * @param {Number} b Starting value |
|
1049 * @param {Number} c Delta between start and end values |
|
1050 * @param {Number} d Total length of animation |
|
1051 * @return {Number} The computed value for the current animation frame |
|
1052 */ |
|
1053 bounceBoth: function (t, b, c, d) { |
|
1054 if (t < d/2) { |
|
1055 return Y.Easing.bounceIn(t * 2, 0, c, d) * 0.5 + b; |
|
1056 } |
|
1057 return Y.Easing.bounceOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; |
|
1058 } |
|
1059 }; |
|
1060 |
|
1061 |
|
1062 |
|
1063 }, '3.0.0b1' ,{requires:['anim-base']}); |
|
1064 |
|
1065 YUI.add('anim-node-plugin', function(Y) { |
|
1066 |
|
1067 /** |
|
1068 * Binds an Anim instance to a Node instance |
|
1069 * @module anim |
|
1070 * @class Plugin.NodeFX |
|
1071 * @extends Base |
|
1072 * @submodule anim-node-plugin |
|
1073 */ |
|
1074 |
|
1075 var NodeFX = function(config) { |
|
1076 config = (config) ? Y.merge(config) : {}; |
|
1077 config.node = config.host; |
|
1078 NodeFX.superclass.constructor.apply(this, arguments); |
|
1079 }; |
|
1080 |
|
1081 NodeFX.NAME = "nodefx"; |
|
1082 NodeFX.NS = "fx"; |
|
1083 |
|
1084 Y.extend(NodeFX, Y.Anim); |
|
1085 |
|
1086 Y.namespace('Plugin'); |
|
1087 Y.Plugin.NodeFX = NodeFX; |
|
1088 |
|
1089 |
|
1090 |
|
1091 }, '3.0.0b1' ,{requires:['anim-base', 'node-base']}); |
|
1092 |
|
1093 YUI.add('anim-scroll', function(Y) { |
|
1094 |
|
1095 /** |
|
1096 * Adds support for the <code>scroll</code> property in <code>to</code> |
|
1097 * and <code>from</code> attributes. |
|
1098 * @module anim |
|
1099 * @submodule anim-scroll |
|
1100 */ |
|
1101 |
|
1102 var NUM = Number; |
|
1103 |
|
1104 //TODO: deprecate for scrollTop/Left properties? |
|
1105 Y.Anim.behaviors.scroll = { |
|
1106 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
1107 var |
|
1108 node = anim._node, |
|
1109 val = ([ |
|
1110 fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration), |
|
1111 fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration) |
|
1112 ]); |
|
1113 |
|
1114 if (val[0]) { |
|
1115 node.set('scrollLeft', val[0]); |
|
1116 } |
|
1117 |
|
1118 if (val[1]) { |
|
1119 node.set('scrollTop', val[1]); |
|
1120 } |
|
1121 }, |
|
1122 get: function(anim) { |
|
1123 var node = anim._node; |
|
1124 return [node.get('scrollLeft'), node.get('scrollTop')]; |
|
1125 } |
|
1126 }; |
|
1127 |
|
1128 |
|
1129 |
|
1130 |
|
1131 }, '3.0.0b1' ,{requires:['anim-base', 'node-base']}); |
|
1132 |
|
1133 YUI.add('anim-xy', function(Y) { |
|
1134 |
|
1135 /** |
|
1136 * Adds support for the <code>xy</code> property in <code>from</code> and |
|
1137 * <code>to</code> attributes. |
|
1138 * @module anim |
|
1139 * @submodule anim-xy |
|
1140 */ |
|
1141 |
|
1142 var NUM = Number; |
|
1143 |
|
1144 Y.Anim.behaviors.xy = { |
|
1145 set: function(anim, att, from, to, elapsed, duration, fn) { |
|
1146 anim._node.setXY([ |
|
1147 fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration), |
|
1148 fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration) |
|
1149 ]); |
|
1150 }, |
|
1151 get: function(anim) { |
|
1152 return anim._node.getXY(); |
|
1153 } |
|
1154 }; |
|
1155 |
|
1156 |
|
1157 |
|
1158 |
|
1159 }, '3.0.0b1' ,{requires:['anim-base', 'node-screen']}); |
|
1160 |
|
1161 |
|
1162 |
|
1163 YUI.add('anim', function(Y){}, '3.0.0b1' ,{skinnable:false, use:['anim-base', 'anim-color', 'anim-curve', 'anim-easing', 'anim-node-plugin', 'anim-scroll', 'anim-xy']}); |
|
1164 |