Skip to content

Commit 0681a54

Browse files
committed
feat(ngAnimate): ensure JS animations recognize $animateCss directly
JS Animations now recognize the response object returned from a call to `$animateCss`. We can now setup our JS animation code to fully rely on $animateCss to take charge without having to call the doneFn callback on our own. ```js // before .animation('.my-css-animation', function($animateCss) { return { enter: function(element, doneFn) { var animator = $animateCss(element, { event: 'enter', structural: true, from: { background: 'red' }, to: { background: 'blue' } }); animator.start().done(doneFn); } }; }); // now .animation('.my-css-animation', function($animateCss) { return { enter: function(element) { return $animateCss(element, { event: 'enter', structural: true, from: { background: 'red' }, to: { background: 'blue' } }); } }; }); ```
1 parent d5683d2 commit 0681a54

File tree

3 files changed

+82
-18
lines changed

3 files changed

+82
-18
lines changed

src/ngAnimate/animateCss.js

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@
3939
* return {
4040
* enter: function(element, doneFn) {
4141
* var height = element[0].offsetHeight;
42-
* var animator = $animateCss(element, {
42+
* return $animateCss(element, {
4343
* from: { height:'0px' },
4444
* to: { height:height + 'px' },
4545
* duration: 1 // one second
4646
* });
47-
* animator.start().done(doneFn);
4847
* }
4948
* }
5049
* }]);
@@ -67,14 +66,13 @@
6766
* return {
6867
* enter: function(element, doneFn) {
6968
* var height = element[0].offsetHeight;
70-
* var animator = $animateCss(element, {
69+
* return $animateCss(element, {
7170
* addClass: 'red large-text pulse-twice',
7271
* easing: 'ease-out',
7372
* from: { height:'0px' },
7473
* to: { height:height + 'px' },
7574
* duration: 1 // one second
7675
* });
77-
* animator.start().done(doneFn);
7876
* }
7977
* }
8078
* }]);
@@ -171,19 +169,14 @@
171169
* applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
172170
* and that changing them will not reconfigure the parameters of the animation.
173171
*
174-
* By calling `animation.start()` we do get back a promise, however, due to the nature of animations we may not want to tap into the default behaviour of
175-
* animations (since they cause a digest to occur which may slow down the animation performance-wise). Therefore instead of calling `then` to capture when
176-
* the animation ends be sure to call `done(callback)` (this is the recommended way to use `$animateCss` within JavaScript-animations).
172+
* ### runner.done() vs runner.then()
173+
* It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
174+
* runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
175+
* Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
176+
* unless you really need a digest to kick off afterwards.
177177
*
178-
* The example below should put this into perspective:
179-
*
180-
* ```js
181-
* var animator = $animateCss(element, { ... });
182-
* animator.start().done(function() {
183-
* // yaay the animation is over
184-
* doneCallback();
185-
* });
186-
* ```
178+
* Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
179+
* (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). Check the [animation code above](#usage) to see how this works.
187180
*
188181
* @param {DOMElement} element the element that will be animated
189182
* @param {object} options the animation-related options that will be applied during the animation

src/ngAnimate/animateJs.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,20 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
145145
args.push(options);
146146

147147
var value = fn.apply(fn, args);
148+
if (value) {
149+
if (isFunction(value.start)) {
150+
value = value.start();
151+
}
152+
153+
if (value instanceof $$AnimateRunner) {
154+
value.done(onDone);
155+
} else if (isFunction(value)) {
156+
// optional onEnd / onCancel callback
157+
return value;
158+
}
159+
}
148160

149-
// optional onEnd / onCancel callback
150-
return isFunction(value) ? value : noop;
161+
return noop;
151162
}
152163

153164
function groupEventedAnimations(element, event, options, animations, fnName) {

test/ngAnimate/animateJsSpec.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,66 @@ describe("ngAnimate $$animateJs", function() {
544544
});
545545
});
546546

547+
they("$prop should asynchronously render the $prop animation when a start/end animator object is returned",
548+
allEvents, function(event) {
549+
550+
inject(function($$rAF, $$AnimateRunner) {
551+
var runner;
552+
animations[event] = function(element, a, b, c) {
553+
return {
554+
start: function() {
555+
log.push('start ' + event);
556+
return runner = new $$AnimateRunner();
557+
}
558+
};
559+
};
560+
561+
runAnimation(event, function() {
562+
log.push('complete');
563+
});
564+
565+
if (event === 'leave') {
566+
expect(log).toEqual(['start leave']);
567+
runner.end();
568+
$$rAF.flush();
569+
expect(log).toEqual(['start leave', 'dom leave', 'complete']);
570+
} else {
571+
expect(log).toEqual(['dom ' + event, 'start ' + event]);
572+
runner.end();
573+
$$rAF.flush();
574+
expect(log).toEqual(['dom ' + event, 'start ' + event, 'complete']);
575+
}
576+
});
577+
});
578+
579+
they("$prop should asynchronously render the $prop animation when an instance of $$AnimateRunner is returned",
580+
allEvents, function(event) {
581+
582+
inject(function($$rAF, $$AnimateRunner) {
583+
var runner;
584+
animations[event] = function(element, a, b, c) {
585+
log.push('start ' + event);
586+
return runner = new $$AnimateRunner();
587+
};
588+
589+
runAnimation(event, function() {
590+
log.push('complete');
591+
});
592+
593+
if (event === 'leave') {
594+
expect(log).toEqual(['start leave']);
595+
runner.end();
596+
$$rAF.flush();
597+
expect(log).toEqual(['start leave', 'dom leave', 'complete']);
598+
} else {
599+
expect(log).toEqual(['dom ' + event, 'start ' + event]);
600+
runner.end();
601+
$$rAF.flush();
602+
expect(log).toEqual(['dom ' + event, 'start ' + event, 'complete']);
603+
}
604+
});
605+
});
606+
547607
they("$prop should asynchronously reject the before animation if the callback function is called with false", otherEvents, function(event) {
548608
inject(function($$rAF, $rootScope) {
549609
var beforeMethod = 'before' + event.charAt(0).toUpperCase() + event.substr(1);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy