Skip to content

Commit d9e9ece

Browse files
manucorporatadamdbradley
authored andcommitted
fix(animation): always run before classes and functions
fixes #8842 fixes #8769
1 parent 217c171 commit d9e9ece

File tree

1 file changed

+90
-70
lines changed

1 file changed

+90
-70
lines changed

src/animations/animation.ts

Lines changed: 90 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CSS, nativeRaf, transitionEnd, nativeTimeout } from '../util/dom';
2-
import { isDefined } from '../util/util';
2+
import { isDefined, assert } from '../util/util';
33

44

55
/**
@@ -297,7 +297,10 @@ export class Animation {
297297
* Play the animation.
298298
*/
299299
play(opts?: PlayOptions) {
300-
const dur = this.getDuration(opts);
300+
// If the animation was already invalidated (it did finish), do nothing
301+
if (!this._raf) {
302+
return;
303+
}
301304

302305
// this is the top level animation and is in full control
303306
// of when the async play() should actually kick off
@@ -311,22 +314,16 @@ export class Animation {
311314
this._clearAsync();
312315

313316
// recursively kicks off the correct progress step for each child animation
317+
// ******** DOM WRITE ****************
314318
this._playInit(opts);
315319

316-
if (this._isAsync) {
317-
// for the root animation only
318-
// set the async TRANSITION END event
319-
// and run onFinishes when the transition ends
320-
// ******** DOM WRITE ****************
321-
this._asyncEnd(dur, true);
322-
}
323-
324320
// doubling up RAFs since this animation was probably triggered
325321
// from an input event, and just having one RAF would have this code
326322
// run within the same frame as the triggering input event, and the
327323
// input event probably already did way too much work for one frame
328-
this._raf && this._raf(() => {
329-
this._raf && this._raf(this._playDomInspect.bind(this, opts));
324+
this._raf(() => {
325+
assert(this._raf, '_raf has to be valid');
326+
this._raf(this._playDomInspect.bind(this, opts));
330327
});
331328
}
332329

@@ -372,21 +369,24 @@ export class Animation {
372369
// elements will be in the DOM, however visibily hidden
373370
// so we can read their dimensions if need be
374371
// ******** DOM READ ****************
375-
this._beforeReadFn();
376-
377-
// ******** DOM READS ABOVE / DOM WRITES BELOW ****************
378-
379-
// fire off all the "before" function that have DOM WRITES in them
380372
// ******** DOM WRITE ****************
381-
this._beforeWriteFn();
373+
this._beforeAnimation();
374+
375+
// for the root animation only
376+
// set the async TRANSITION END event
377+
// and run onFinishes when the transition ends
378+
const dur = this.getDuration(opts);
379+
if (this._isAsync) {
380+
this._asyncEnd(dur, true);
381+
}
382382

383383
// ******** DOM WRITE ****************
384384
this._playProgress(opts);
385385

386-
if (this._isAsync) {
386+
if (this._isAsync && this._raf) {
387387
// this animation has a duration so we need another RAF
388388
// for the CSS TRANSITION properties to kick in
389-
this._raf && this._raf(this._playToStep.bind(this, 1));
389+
this._raf(this._playToStep.bind(this, 1));
390390
}
391391
}
392392

@@ -401,10 +401,6 @@ export class Animation {
401401
this._c[i]._playProgress(opts);
402402
}
403403

404-
// stage all of the before css classes and inline styles
405-
// ******** DOM WRITE ****************
406-
this._before();
407-
408404
if (this._hasDur) {
409405
// set the CSS TRANSITION duration/easing
410406
// ******** DOM WRITE ****************
@@ -418,7 +414,7 @@ export class Animation {
418414

419415
// since there was no animation, immediately run the after
420416
// ******** DOM WRITE ****************
421-
this._after();
417+
this._afterAnimation();
422418

423419
// this animation has no duration, so it has finished
424420
// other animations could still be running
@@ -517,7 +513,7 @@ export class Animation {
517513

518514
// set the after styles
519515
// ******** DOM WRITE ****************
520-
this._after();
516+
this._afterAnimation();
521517

522518
// remove the will-change properties
523519
// ******** DOM WRITE ****************
@@ -684,38 +680,69 @@ export class Animation {
684680

685681
/**
686682
* @private
683+
* DOM READ
687684
* DOM WRITE
688-
* NO RECURSION
685+
* RECURSION
689686
*/
690-
_before() {
687+
_beforeAnimation() {
688+
// fire off all the "before" function that have DOM READS in them
689+
// elements will be in the DOM, however visibily hidden
690+
// so we can read their dimensions if need be
691+
// ******** DOM READ ****************
692+
this._fireBeforeReadFunc();
693+
694+
// ******** DOM READS ABOVE / DOM WRITES BELOW ****************
695+
696+
// fire off all the "before" function that have DOM WRITES in them
697+
// ******** DOM WRITE ****************
698+
this._fireBeforeWriteFunc();
699+
700+
// stage all of the before css classes and inline styles
701+
// ******** DOM WRITE ****************
702+
this._setBeforeStyles();
703+
}
704+
705+
/**
706+
* @private
707+
* DOM WRITE
708+
* RECURSION
709+
*/
710+
_setBeforeStyles() {
711+
for (var i = 0; i < this._cL; i++) {
712+
this._c[i]._setBeforeStyles();
713+
}
714+
691715
// before the animations have started
692-
if (!this._rv) {
693-
let ele: HTMLElement;
694-
for (var i = 0; i < this._eL; i++) {
695-
ele = this._e[i];
716+
// only set before styles if animation is not reversed
717+
if (this._rv) {
718+
return;
719+
}
696720

697-
// css classes to add before the animation
698-
if (this._bfAdd) {
699-
for (var j = 0; j < this._bfAdd.length; j++) {
700-
// ******** DOM WRITE ****************
701-
ele.classList.add(this._bfAdd[j]);
702-
}
721+
let ele: HTMLElement;
722+
for (var i = 0; i < this._eL; i++) {
723+
ele = this._e[i];
724+
725+
// css classes to add before the animation
726+
if (this._bfAdd) {
727+
for (var j = 0; j < this._bfAdd.length; j++) {
728+
// ******** DOM WRITE ****************
729+
ele.classList.add(this._bfAdd[j]);
703730
}
731+
}
704732

705-
// css classes to remove before the animation
706-
if (this._bfRm) {
707-
for (var j = 0; j < this._bfRm.length; j++) {
708-
// ******** DOM WRITE ****************
709-
ele.classList.remove(this._bfRm[j]);
710-
}
733+
// css classes to remove before the animation
734+
if (this._bfRm) {
735+
for (var j = 0; j < this._bfRm.length; j++) {
736+
// ******** DOM WRITE ****************
737+
ele.classList.remove(this._bfRm[j]);
711738
}
739+
}
712740

713-
// inline styles to add before the animation
714-
if (this._bfSty) {
715-
for (var prop in this._bfSty) {
716-
// ******** DOM WRITE ****************
717-
(<any>ele).style[prop] = this._bfSty[prop];
718-
}
741+
// inline styles to add before the animation
742+
if (this._bfSty) {
743+
for (var prop in this._bfSty) {
744+
// ******** DOM WRITE ****************
745+
(<any>ele).style[prop] = this._bfSty[prop];
719746
}
720747
}
721748
}
@@ -726,10 +753,10 @@ export class Animation {
726753
* DOM READ
727754
* RECURSION
728755
*/
729-
_beforeReadFn() {
756+
_fireBeforeReadFunc() {
730757
for (var i = 0; i < this._cL; i++) {
731758
// ******** DOM READ ****************
732-
this._c[i]._beforeReadFn();
759+
this._c[i]._fireBeforeReadFunc();
733760
}
734761

735762
if (this._rdFn) {
@@ -745,10 +772,10 @@ export class Animation {
745772
* DOM WRITE
746773
* RECURSION
747774
*/
748-
_beforeWriteFn() {
775+
_fireBeforeWriteFunc() {
749776
for (var i = 0; i < this._cL; i++) {
750777
// ******** DOM WRITE ****************
751-
this._c[i]._beforeWriteFn();
778+
this._c[i]._fireBeforeWriteFunc();
752779
}
753780

754781
if (this._wrFn) {
@@ -762,9 +789,13 @@ export class Animation {
762789
/**
763790
* @private
764791
* DOM WRITE
765-
* NO RECURSION
792+
* RECURSION
766793
*/
767-
_after() {
794+
_afterAnimation() {
795+
for (var i = 0; i < this._cL; i++) {
796+
this._c[i]._afterAnimation();
797+
}
798+
768799
let ele: HTMLElement;
769800
for (var i = 0; i < this._eL; i++) {
770801
ele = this._e[i];
@@ -828,7 +859,6 @@ export class Animation {
828859
}
829860
}
830861
}
831-
832862
}
833863

834864
/**
@@ -864,15 +894,8 @@ export class Animation {
864894
// ensure all past transition end events have been cleared
865895
this._clearAsync();
866896

867-
// fire off all the "before" function that have DOM READS in them
868-
// elements will be in the DOM, however visibily hidden
869-
// so we can read their dimensions if need be
870-
// ******** DOM READ ****************
871-
this._beforeReadFn();
872-
873-
// fire off all the "before" function that have DOM WRITES in them
874-
// ******** DOM WRITE ****************
875-
this._beforeWriteFn();
897+
// ******** DOM READ/WRITE ****************
898+
this._beforeAnimation();
876899

877900
// ******** DOM WRITE ****************
878901
this._progressStart();
@@ -889,9 +912,6 @@ export class Animation {
889912
this._c[i]._progressStart();
890913
}
891914

892-
// ******** DOM WRITE ****************
893-
this._before();
894-
895915
// force no duration, linear easing
896916
// ******** DOM WRITE ****************
897917
this._setTrans(0, true);
@@ -971,7 +991,7 @@ export class Animation {
971991
// ******** DOM WRITE ****************
972992
this._progress(stepValue);
973993
this._willChg(false);
974-
this._after();
994+
this._afterAnimation();
975995
this._didFinish(shouldComplete);
976996

977997
} else {

0 commit comments

Comments
 (0)