1 | define(["./kernel", "./lang", "../Evented", "./Color", "./connect", "./sniff", "../dom", "../dom-style"], function(dojo, lang, Evented, Color, connect, has, dom, style){ |
---|
2 | // module: |
---|
3 | // dojo/_base/fx |
---|
4 | // summary: |
---|
5 | // This module defines the base dojo.fx implementation. |
---|
6 | // notes: |
---|
7 | // Animation loosely package based on Dan Pupius' work, contributed under CLA; see |
---|
8 | // http://pupius.co.uk/js/Toolkit.Drawing.js |
---|
9 | |
---|
10 | var _mixin = lang.mixin; |
---|
11 | |
---|
12 | dojo._Line = function(/*int*/ start, /*int*/ end){ |
---|
13 | // summary: |
---|
14 | // dojo._Line is the object used to generate values from a start value |
---|
15 | // to an end value |
---|
16 | // start: int |
---|
17 | // Beginning value for range |
---|
18 | // end: int |
---|
19 | // Ending value for range |
---|
20 | this.start = start; |
---|
21 | this.end = end; |
---|
22 | }; |
---|
23 | |
---|
24 | dojo._Line.prototype.getValue = function(/*float*/ n){ |
---|
25 | // summary: Returns the point on the line |
---|
26 | // n: a floating point number greater than 0 and less than 1 |
---|
27 | return ((this.end - this.start) * n) + this.start; // Decimal |
---|
28 | }; |
---|
29 | |
---|
30 | dojo.Animation = function(args){ |
---|
31 | // summary: |
---|
32 | // A generic animation class that fires callbacks into its handlers |
---|
33 | // object at various states. |
---|
34 | // description: |
---|
35 | // A generic animation class that fires callbacks into its handlers |
---|
36 | // object at various states. Nearly all dojo animation functions |
---|
37 | // return an instance of this method, usually without calling the |
---|
38 | // .play() method beforehand. Therefore, you will likely need to |
---|
39 | // call .play() on instances of `dojo.Animation` when one is |
---|
40 | // returned. |
---|
41 | // args: Object |
---|
42 | // The 'magic argument', mixing all the properties into this |
---|
43 | // animation instance. |
---|
44 | |
---|
45 | _mixin(this, args); |
---|
46 | if(lang.isArray(this.curve)){ |
---|
47 | this.curve = new dojo._Line(this.curve[0], this.curve[1]); |
---|
48 | } |
---|
49 | |
---|
50 | }; |
---|
51 | dojo.Animation.prototype = new Evented(); |
---|
52 | // Alias to drop come 2.0: |
---|
53 | dojo._Animation = dojo.Animation; |
---|
54 | |
---|
55 | lang.extend(dojo.Animation, { |
---|
56 | // duration: Integer |
---|
57 | // The time in milliseonds the animation will take to run |
---|
58 | duration: 350, |
---|
59 | |
---|
60 | /*===== |
---|
61 | // curve: dojo._Line|Array |
---|
62 | // A two element array of start and end values, or a `dojo._Line` instance to be |
---|
63 | // used in the Animation. |
---|
64 | curve: null, |
---|
65 | |
---|
66 | // easing: Function? |
---|
67 | // A Function to adjust the acceleration (or deceleration) of the progress |
---|
68 | // across a dojo._Line |
---|
69 | easing: null, |
---|
70 | =====*/ |
---|
71 | |
---|
72 | // repeat: Integer? |
---|
73 | // The number of times to loop the animation |
---|
74 | repeat: 0, |
---|
75 | |
---|
76 | // rate: Integer? |
---|
77 | // the time in milliseconds to wait before advancing to next frame |
---|
78 | // (used as a fps timer: 1000/rate = fps) |
---|
79 | rate: 20 /* 50 fps */, |
---|
80 | |
---|
81 | /*===== |
---|
82 | // delay: Integer? |
---|
83 | // The time in milliseconds to wait before starting animation after it |
---|
84 | // has been .play()'ed |
---|
85 | delay: null, |
---|
86 | |
---|
87 | // beforeBegin: Event? |
---|
88 | // Synthetic event fired before a dojo.Animation begins playing (synchronous) |
---|
89 | beforeBegin: null, |
---|
90 | |
---|
91 | // onBegin: Event? |
---|
92 | // Synthetic event fired as a dojo.Animation begins playing (useful?) |
---|
93 | onBegin: null, |
---|
94 | |
---|
95 | // onAnimate: Event? |
---|
96 | // Synthetic event fired at each interval of a `dojo.Animation` |
---|
97 | onAnimate: null, |
---|
98 | |
---|
99 | // onEnd: Event? |
---|
100 | // Synthetic event fired after the final frame of a `dojo.Animation` |
---|
101 | onEnd: null, |
---|
102 | |
---|
103 | // onPlay: Event? |
---|
104 | // Synthetic event fired any time a `dojo.Animation` is play()'ed |
---|
105 | onPlay: null, |
---|
106 | |
---|
107 | // onPause: Event? |
---|
108 | // Synthetic event fired when a `dojo.Animation` is paused |
---|
109 | onPause: null, |
---|
110 | |
---|
111 | // onStop: Event |
---|
112 | // Synthetic event fires when a `dojo.Animation` is stopped |
---|
113 | onStop: null, |
---|
114 | |
---|
115 | =====*/ |
---|
116 | |
---|
117 | _percent: 0, |
---|
118 | _startRepeatCount: 0, |
---|
119 | |
---|
120 | _getStep: function(){ |
---|
121 | var _p = this._percent, |
---|
122 | _e = this.easing |
---|
123 | ; |
---|
124 | return _e ? _e(_p) : _p; |
---|
125 | }, |
---|
126 | _fire: function(/*Event*/ evt, /*Array?*/ args){ |
---|
127 | // summary: |
---|
128 | // Convenience function. Fire event "evt" and pass it the |
---|
129 | // arguments specified in "args". |
---|
130 | // description: |
---|
131 | // Convenience function. Fire event "evt" and pass it the |
---|
132 | // arguments specified in "args". |
---|
133 | // Fires the callback in the scope of the `dojo.Animation` |
---|
134 | // instance. |
---|
135 | // evt: |
---|
136 | // The event to fire. |
---|
137 | // args: |
---|
138 | // The arguments to pass to the event. |
---|
139 | var a = args||[]; |
---|
140 | if(this[evt]){ |
---|
141 | if(dojo.config.debugAtAllCosts){ |
---|
142 | this[evt].apply(this, a); |
---|
143 | }else{ |
---|
144 | try{ |
---|
145 | this[evt].apply(this, a); |
---|
146 | }catch(e){ |
---|
147 | // squelch and log because we shouldn't allow exceptions in |
---|
148 | // synthetic event handlers to cause the internal timer to run |
---|
149 | // amuck, potentially pegging the CPU. I'm not a fan of this |
---|
150 | // squelch, but hopefully logging will make it clear what's |
---|
151 | // going on |
---|
152 | console.error("exception in animation handler for:", evt); |
---|
153 | console.error(e); |
---|
154 | } |
---|
155 | } |
---|
156 | } |
---|
157 | return this; // dojo.Animation |
---|
158 | }, |
---|
159 | |
---|
160 | play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ |
---|
161 | // summary: |
---|
162 | // Start the animation. |
---|
163 | // delay: |
---|
164 | // How many milliseconds to delay before starting. |
---|
165 | // gotoStart: |
---|
166 | // If true, starts the animation from the beginning; otherwise, |
---|
167 | // starts it from its current position. |
---|
168 | // returns: dojo.Animation |
---|
169 | // The instance to allow chaining. |
---|
170 | |
---|
171 | var _t = this; |
---|
172 | if(_t._delayTimer){ _t._clearTimer(); } |
---|
173 | if(gotoStart){ |
---|
174 | _t._stopTimer(); |
---|
175 | _t._active = _t._paused = false; |
---|
176 | _t._percent = 0; |
---|
177 | }else if(_t._active && !_t._paused){ |
---|
178 | return _t; |
---|
179 | } |
---|
180 | |
---|
181 | _t._fire("beforeBegin", [_t.node]); |
---|
182 | |
---|
183 | var de = delay || _t.delay, |
---|
184 | _p = lang.hitch(_t, "_play", gotoStart); |
---|
185 | |
---|
186 | if(de > 0){ |
---|
187 | _t._delayTimer = setTimeout(_p, de); |
---|
188 | return _t; |
---|
189 | } |
---|
190 | _p(); |
---|
191 | return _t; // dojo.Animation |
---|
192 | }, |
---|
193 | |
---|
194 | _play: function(gotoStart){ |
---|
195 | var _t = this; |
---|
196 | if(_t._delayTimer){ _t._clearTimer(); } |
---|
197 | _t._startTime = new Date().valueOf(); |
---|
198 | if(_t._paused){ |
---|
199 | _t._startTime -= _t.duration * _t._percent; |
---|
200 | } |
---|
201 | |
---|
202 | _t._active = true; |
---|
203 | _t._paused = false; |
---|
204 | var value = _t.curve.getValue(_t._getStep()); |
---|
205 | if(!_t._percent){ |
---|
206 | if(!_t._startRepeatCount){ |
---|
207 | _t._startRepeatCount = _t.repeat; |
---|
208 | } |
---|
209 | _t._fire("onBegin", [value]); |
---|
210 | } |
---|
211 | |
---|
212 | _t._fire("onPlay", [value]); |
---|
213 | |
---|
214 | _t._cycle(); |
---|
215 | return _t; // dojo.Animation |
---|
216 | }, |
---|
217 | |
---|
218 | pause: function(){ |
---|
219 | // summary: Pauses a running animation. |
---|
220 | var _t = this; |
---|
221 | if(_t._delayTimer){ _t._clearTimer(); } |
---|
222 | _t._stopTimer(); |
---|
223 | if(!_t._active){ return _t; /*dojo.Animation*/ } |
---|
224 | _t._paused = true; |
---|
225 | _t._fire("onPause", [_t.curve.getValue(_t._getStep())]); |
---|
226 | return _t; // dojo.Animation |
---|
227 | }, |
---|
228 | |
---|
229 | gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){ |
---|
230 | // summary: |
---|
231 | // Sets the progress of the animation. |
---|
232 | // percent: |
---|
233 | // A percentage in decimal notation (between and including 0.0 and 1.0). |
---|
234 | // andPlay: |
---|
235 | // If true, play the animation after setting the progress. |
---|
236 | var _t = this; |
---|
237 | _t._stopTimer(); |
---|
238 | _t._active = _t._paused = true; |
---|
239 | _t._percent = percent; |
---|
240 | if(andPlay){ _t.play(); } |
---|
241 | return _t; // dojo.Animation |
---|
242 | }, |
---|
243 | |
---|
244 | stop: function(/*boolean?*/ gotoEnd){ |
---|
245 | // summary: Stops a running animation. |
---|
246 | // gotoEnd: If true, the animation will end. |
---|
247 | var _t = this; |
---|
248 | if(_t._delayTimer){ _t._clearTimer(); } |
---|
249 | if(!_t._timer){ return _t; /* dojo.Animation */ } |
---|
250 | _t._stopTimer(); |
---|
251 | if(gotoEnd){ |
---|
252 | _t._percent = 1; |
---|
253 | } |
---|
254 | _t._fire("onStop", [_t.curve.getValue(_t._getStep())]); |
---|
255 | _t._active = _t._paused = false; |
---|
256 | return _t; // dojo.Animation |
---|
257 | }, |
---|
258 | |
---|
259 | status: function(){ |
---|
260 | // summary: |
---|
261 | // Returns a string token representation of the status of |
---|
262 | // the animation, one of: "paused", "playing", "stopped" |
---|
263 | if(this._active){ |
---|
264 | return this._paused ? "paused" : "playing"; // String |
---|
265 | } |
---|
266 | return "stopped"; // String |
---|
267 | }, |
---|
268 | |
---|
269 | _cycle: function(){ |
---|
270 | var _t = this; |
---|
271 | if(_t._active){ |
---|
272 | var curr = new Date().valueOf(); |
---|
273 | var step = (curr - _t._startTime) / (_t.duration); |
---|
274 | |
---|
275 | if(step >= 1){ |
---|
276 | step = 1; |
---|
277 | } |
---|
278 | _t._percent = step; |
---|
279 | |
---|
280 | // Perform easing |
---|
281 | if(_t.easing){ |
---|
282 | step = _t.easing(step); |
---|
283 | } |
---|
284 | |
---|
285 | _t._fire("onAnimate", [_t.curve.getValue(step)]); |
---|
286 | |
---|
287 | if(_t._percent < 1){ |
---|
288 | _t._startTimer(); |
---|
289 | }else{ |
---|
290 | _t._active = false; |
---|
291 | |
---|
292 | if(_t.repeat > 0){ |
---|
293 | _t.repeat--; |
---|
294 | _t.play(null, true); |
---|
295 | }else if(_t.repeat == -1){ |
---|
296 | _t.play(null, true); |
---|
297 | }else{ |
---|
298 | if(_t._startRepeatCount){ |
---|
299 | _t.repeat = _t._startRepeatCount; |
---|
300 | _t._startRepeatCount = 0; |
---|
301 | } |
---|
302 | } |
---|
303 | _t._percent = 0; |
---|
304 | _t._fire("onEnd", [_t.node]); |
---|
305 | !_t.repeat && _t._stopTimer(); |
---|
306 | } |
---|
307 | } |
---|
308 | return _t; // dojo.Animation |
---|
309 | }, |
---|
310 | |
---|
311 | _clearTimer: function(){ |
---|
312 | // summary: Clear the play delay timer |
---|
313 | clearTimeout(this._delayTimer); |
---|
314 | delete this._delayTimer; |
---|
315 | } |
---|
316 | |
---|
317 | }); |
---|
318 | |
---|
319 | // the local timer, stubbed into all Animation instances |
---|
320 | var ctr = 0, |
---|
321 | timer = null, |
---|
322 | runner = { |
---|
323 | run: function(){} |
---|
324 | }; |
---|
325 | |
---|
326 | lang.extend(dojo.Animation, { |
---|
327 | |
---|
328 | _startTimer: function(){ |
---|
329 | if(!this._timer){ |
---|
330 | this._timer = connect.connect(runner, "run", this, "_cycle"); |
---|
331 | ctr++; |
---|
332 | } |
---|
333 | if(!timer){ |
---|
334 | timer = setInterval(lang.hitch(runner, "run"), this.rate); |
---|
335 | } |
---|
336 | }, |
---|
337 | |
---|
338 | _stopTimer: function(){ |
---|
339 | if(this._timer){ |
---|
340 | connect.disconnect(this._timer); |
---|
341 | this._timer = null; |
---|
342 | ctr--; |
---|
343 | } |
---|
344 | if(ctr <= 0){ |
---|
345 | clearInterval(timer); |
---|
346 | timer = null; |
---|
347 | ctr = 0; |
---|
348 | } |
---|
349 | } |
---|
350 | |
---|
351 | }); |
---|
352 | |
---|
353 | var _makeFadeable = |
---|
354 | //>>excludeStart("webkitMobile", kwArgs.webkitMobile); |
---|
355 | has("ie") ? function(node){ |
---|
356 | // only set the zoom if the "tickle" value would be the same as the |
---|
357 | // default |
---|
358 | var ns = node.style; |
---|
359 | // don't set the width to auto if it didn't already cascade that way. |
---|
360 | // We don't want to f anyones designs |
---|
361 | if(!ns.width.length && style.get(node, "width") == "auto"){ |
---|
362 | ns.width = "auto"; |
---|
363 | } |
---|
364 | } : |
---|
365 | //>>excludeEnd("webkitMobile"); |
---|
366 | function(){}; |
---|
367 | |
---|
368 | dojo._fade = function(/*Object*/ args){ |
---|
369 | // summary: |
---|
370 | // Returns an animation that will fade the node defined by |
---|
371 | // args.node from the start to end values passed (args.start |
---|
372 | // args.end) (end is mandatory, start is optional) |
---|
373 | |
---|
374 | args.node = dom.byId(args.node); |
---|
375 | var fArgs = _mixin({ properties: {} }, args), |
---|
376 | props = (fArgs.properties.opacity = {}); |
---|
377 | |
---|
378 | props.start = !("start" in fArgs) ? |
---|
379 | function(){ |
---|
380 | return +style.get(fArgs.node, "opacity")||0; |
---|
381 | } : fArgs.start; |
---|
382 | props.end = fArgs.end; |
---|
383 | |
---|
384 | var anim = dojo.animateProperty(fArgs); |
---|
385 | connect.connect(anim, "beforeBegin", lang.partial(_makeFadeable, fArgs.node)); |
---|
386 | |
---|
387 | return anim; // dojo.Animation |
---|
388 | }; |
---|
389 | |
---|
390 | /*===== |
---|
391 | dojo.__FadeArgs = function(node, duration, easing){ |
---|
392 | // node: DOMNode|String |
---|
393 | // The node referenced in the animation |
---|
394 | // duration: Integer? |
---|
395 | // Duration of the animation in milliseconds. |
---|
396 | // easing: Function? |
---|
397 | // An easing function. |
---|
398 | this.node = node; |
---|
399 | this.duration = duration; |
---|
400 | this.easing = easing; |
---|
401 | } |
---|
402 | =====*/ |
---|
403 | |
---|
404 | dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){ |
---|
405 | // summary: |
---|
406 | // Returns an animation that will fade node defined in 'args' from |
---|
407 | // its current opacity to fully opaque. |
---|
408 | return dojo._fade(_mixin({ end: 1 }, args)); // dojo.Animation |
---|
409 | }; |
---|
410 | |
---|
411 | dojo.fadeOut = function(/*dojo.__FadeArgs*/ args){ |
---|
412 | // summary: |
---|
413 | // Returns an animation that will fade node defined in 'args' |
---|
414 | // from its current opacity to fully transparent. |
---|
415 | return dojo._fade(_mixin({ end: 0 }, args)); // dojo.Animation |
---|
416 | }; |
---|
417 | |
---|
418 | dojo._defaultEasing = function(/*Decimal?*/ n){ |
---|
419 | // summary: The default easing function for dojo.Animation(s) |
---|
420 | return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2); // Decimal |
---|
421 | }; |
---|
422 | |
---|
423 | var PropLine = function(properties){ |
---|
424 | // PropLine is an internal class which is used to model the values of |
---|
425 | // an a group of CSS properties across an animation lifecycle. In |
---|
426 | // particular, the "getValue" function handles getting interpolated |
---|
427 | // values between start and end for a particular CSS value. |
---|
428 | this._properties = properties; |
---|
429 | for(var p in properties){ |
---|
430 | var prop = properties[p]; |
---|
431 | if(prop.start instanceof Color){ |
---|
432 | // create a reusable temp color object to keep intermediate results |
---|
433 | prop.tempColor = new Color(); |
---|
434 | } |
---|
435 | } |
---|
436 | }; |
---|
437 | |
---|
438 | PropLine.prototype.getValue = function(r){ |
---|
439 | var ret = {}; |
---|
440 | for(var p in this._properties){ |
---|
441 | var prop = this._properties[p], |
---|
442 | start = prop.start; |
---|
443 | if(start instanceof Color){ |
---|
444 | ret[p] = Color.blendColors(start, prop.end, r, prop.tempColor).toCss(); |
---|
445 | }else if(!lang.isArray(start)){ |
---|
446 | ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0); |
---|
447 | } |
---|
448 | } |
---|
449 | return ret; |
---|
450 | }; |
---|
451 | |
---|
452 | /*===== |
---|
453 | dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], { |
---|
454 | // Properties: Object? |
---|
455 | // A hash map of style properties to Objects describing the transition, |
---|
456 | // such as the properties of dojo._Line with an additional 'units' property |
---|
457 | properties: {} |
---|
458 | |
---|
459 | //TODOC: add event callbacks |
---|
460 | }); |
---|
461 | =====*/ |
---|
462 | |
---|
463 | dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){ |
---|
464 | // summary: |
---|
465 | // Returns an animation that will transition the properties of |
---|
466 | // node defined in `args` depending how they are defined in |
---|
467 | // `args.properties` |
---|
468 | // |
---|
469 | // description: |
---|
470 | // `dojo.animateProperty` is the foundation of most `dojo.fx` |
---|
471 | // animations. It takes an object of "properties" corresponding to |
---|
472 | // style properties, and animates them in parallel over a set |
---|
473 | // duration. |
---|
474 | // |
---|
475 | // example: |
---|
476 | // A simple animation that changes the width of the specified node. |
---|
477 | // | dojo.animateProperty({ |
---|
478 | // | node: "nodeId", |
---|
479 | // | properties: { width: 400 }, |
---|
480 | // | }).play(); |
---|
481 | // Dojo figures out the start value for the width and converts the |
---|
482 | // integer specified for the width to the more expressive but |
---|
483 | // verbose form `{ width: { end: '400', units: 'px' } }` which you |
---|
484 | // can also specify directly. Defaults to 'px' if ommitted. |
---|
485 | // |
---|
486 | // example: |
---|
487 | // Animate width, height, and padding over 2 seconds... the |
---|
488 | // pedantic way: |
---|
489 | // | dojo.animateProperty({ node: node, duration:2000, |
---|
490 | // | properties: { |
---|
491 | // | width: { start: '200', end: '400', units:"px" }, |
---|
492 | // | height: { start:'200', end: '400', units:"px" }, |
---|
493 | // | paddingTop: { start:'5', end:'50', units:"px" } |
---|
494 | // | } |
---|
495 | // | }).play(); |
---|
496 | // Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties |
---|
497 | // are written using "mixed case", as the hyphen is illegal as an object key. |
---|
498 | // |
---|
499 | // example: |
---|
500 | // Plug in a different easing function and register a callback for |
---|
501 | // when the animation ends. Easing functions accept values between |
---|
502 | // zero and one and return a value on that basis. In this case, an |
---|
503 | // exponential-in curve. |
---|
504 | // | dojo.animateProperty({ |
---|
505 | // | node: "nodeId", |
---|
506 | // | // dojo figures out the start value |
---|
507 | // | properties: { width: { end: 400 } }, |
---|
508 | // | easing: function(n){ |
---|
509 | // | return (n==0) ? 0 : Math.pow(2, 10 * (n - 1)); |
---|
510 | // | }, |
---|
511 | // | onEnd: function(node){ |
---|
512 | // | // called when the animation finishes. The animation |
---|
513 | // | // target is passed to this function |
---|
514 | // | } |
---|
515 | // | }).play(500); // delay playing half a second |
---|
516 | // |
---|
517 | // example: |
---|
518 | // Like all `dojo.Animation`s, animateProperty returns a handle to the |
---|
519 | // Animation instance, which fires the events common to Dojo FX. Use `dojo.connect` |
---|
520 | // to access these events outside of the Animation definiton: |
---|
521 | // | var anim = dojo.animateProperty({ |
---|
522 | // | node:"someId", |
---|
523 | // | properties:{ |
---|
524 | // | width:400, height:500 |
---|
525 | // | } |
---|
526 | // | }); |
---|
527 | // | dojo.connect(anim,"onEnd", function(){ |
---|
528 | // | console.log("animation ended"); |
---|
529 | // | }); |
---|
530 | // | // play the animation now: |
---|
531 | // | anim.play(); |
---|
532 | // |
---|
533 | // example: |
---|
534 | // Each property can be a function whose return value is substituted along. |
---|
535 | // Additionally, each measurement (eg: start, end) can be a function. The node |
---|
536 | // reference is passed direcly to callbacks. |
---|
537 | // | dojo.animateProperty({ |
---|
538 | // | node:"mine", |
---|
539 | // | properties:{ |
---|
540 | // | height:function(node){ |
---|
541 | // | // shrink this node by 50% |
---|
542 | // | return dojo.position(node).h / 2 |
---|
543 | // | }, |
---|
544 | // | width:{ |
---|
545 | // | start:function(node){ return 100; }, |
---|
546 | // | end:function(node){ return 200; } |
---|
547 | // | } |
---|
548 | // | } |
---|
549 | // | }).play(); |
---|
550 | // |
---|
551 | |
---|
552 | var n = args.node = dom.byId(args.node); |
---|
553 | if(!args.easing){ args.easing = dojo._defaultEasing; } |
---|
554 | |
---|
555 | var anim = new dojo.Animation(args); |
---|
556 | connect.connect(anim, "beforeBegin", anim, function(){ |
---|
557 | var pm = {}; |
---|
558 | for(var p in this.properties){ |
---|
559 | // Make shallow copy of properties into pm because we overwrite |
---|
560 | // some values below. In particular if start/end are functions |
---|
561 | // we don't want to overwrite them or the functions won't be |
---|
562 | // called if the animation is reused. |
---|
563 | if(p == "width" || p == "height"){ |
---|
564 | this.node.display = "block"; |
---|
565 | } |
---|
566 | var prop = this.properties[p]; |
---|
567 | if(lang.isFunction(prop)){ |
---|
568 | prop = prop(n); |
---|
569 | } |
---|
570 | prop = pm[p] = _mixin({}, (lang.isObject(prop) ? prop: { end: prop })); |
---|
571 | |
---|
572 | if(lang.isFunction(prop.start)){ |
---|
573 | prop.start = prop.start(n); |
---|
574 | } |
---|
575 | if(lang.isFunction(prop.end)){ |
---|
576 | prop.end = prop.end(n); |
---|
577 | } |
---|
578 | var isColor = (p.toLowerCase().indexOf("color") >= 0); |
---|
579 | function getStyle(node, p){ |
---|
580 | // dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable: |
---|
581 | var v = { height: node.offsetHeight, width: node.offsetWidth }[p]; |
---|
582 | if(v !== undefined){ return v; } |
---|
583 | v = style.get(node, p); |
---|
584 | return (p == "opacity") ? +v : (isColor ? v : parseFloat(v)); |
---|
585 | } |
---|
586 | if(!("end" in prop)){ |
---|
587 | prop.end = getStyle(n, p); |
---|
588 | }else if(!("start" in prop)){ |
---|
589 | prop.start = getStyle(n, p); |
---|
590 | } |
---|
591 | |
---|
592 | if(isColor){ |
---|
593 | prop.start = new Color(prop.start); |
---|
594 | prop.end = new Color(prop.end); |
---|
595 | }else{ |
---|
596 | prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start); |
---|
597 | } |
---|
598 | } |
---|
599 | this.curve = new PropLine(pm); |
---|
600 | }); |
---|
601 | connect.connect(anim, "onAnimate", lang.hitch(style, "set", anim.node)); |
---|
602 | return anim; // dojo.Animation |
---|
603 | }; |
---|
604 | |
---|
605 | dojo.anim = function( /*DOMNode|String*/ node, |
---|
606 | /*Object*/ properties, |
---|
607 | /*Integer?*/ duration, |
---|
608 | /*Function?*/ easing, |
---|
609 | /*Function?*/ onEnd, |
---|
610 | /*Integer?*/ delay){ |
---|
611 | // summary: |
---|
612 | // A simpler interface to `dojo.animateProperty()`, also returns |
---|
613 | // an instance of `dojo.Animation` but begins the animation |
---|
614 | // immediately, unlike nearly every other Dojo animation API. |
---|
615 | // description: |
---|
616 | // `dojo.anim` is a simpler (but somewhat less powerful) version |
---|
617 | // of `dojo.animateProperty`. It uses defaults for many basic properties |
---|
618 | // and allows for positional parameters to be used in place of the |
---|
619 | // packed "property bag" which is used for other Dojo animation |
---|
620 | // methods. |
---|
621 | // |
---|
622 | // The `dojo.Animation` object returned from `dojo.anim` will be |
---|
623 | // already playing when it is returned from this function, so |
---|
624 | // calling play() on it again is (usually) a no-op. |
---|
625 | // node: |
---|
626 | // a DOM node or the id of a node to animate CSS properties on |
---|
627 | // duration: |
---|
628 | // The number of milliseconds over which the animation |
---|
629 | // should run. Defaults to the global animation default duration |
---|
630 | // (350ms). |
---|
631 | // easing: |
---|
632 | // An easing function over which to calculate acceleration |
---|
633 | // and deceleration of the animation through its duration. |
---|
634 | // A default easing algorithm is provided, but you may |
---|
635 | // plug in any you wish. A large selection of easing algorithms |
---|
636 | // are available in `dojo.fx.easing`. |
---|
637 | // onEnd: |
---|
638 | // A function to be called when the animation finishes |
---|
639 | // running. |
---|
640 | // delay: |
---|
641 | // The number of milliseconds to delay beginning the |
---|
642 | // animation by. The default is 0. |
---|
643 | // example: |
---|
644 | // Fade out a node |
---|
645 | // | dojo.anim("id", { opacity: 0 }); |
---|
646 | // example: |
---|
647 | // Fade out a node over a full second |
---|
648 | // | dojo.anim("id", { opacity: 0 }, 1000); |
---|
649 | return dojo.animateProperty({ // dojo.Animation |
---|
650 | node: node, |
---|
651 | duration: duration || dojo.Animation.prototype.duration, |
---|
652 | properties: properties, |
---|
653 | easing: easing, |
---|
654 | onEnd: onEnd |
---|
655 | }).play(delay || 0); |
---|
656 | }; |
---|
657 | |
---|
658 | return { |
---|
659 | _Line: dojo._Line, |
---|
660 | Animation: dojo.Animation, |
---|
661 | _fade: dojo._fade, |
---|
662 | fadeIn: dojo.fadeIn, |
---|
663 | fadeOut: dojo.fadeOut, |
---|
664 | _defaultEasing: dojo._defaultEasing, |
---|
665 | animateProperty: dojo.animateProperty, |
---|
666 | anim: dojo.anim |
---|
667 | }; |
---|
668 | }); |
---|