@@ -114,7 +114,7 @@ export class RippleRenderer implements EventListenerObject {
114
114
const radius = config . radius || distanceToFurthestCorner ( x , y , containerRect ) ;
115
115
const offsetX = x - containerRect . left ;
116
116
const offsetY = y - containerRect . top ;
117
- const duration = animationConfig . enterDuration ;
117
+ const enterDuration = animationConfig . enterDuration ;
118
118
119
119
const ripple = document . createElement ( 'div' ) ;
120
120
ripple . classList . add ( 'mat-ripple-element' ) ;
@@ -130,20 +130,30 @@ export class RippleRenderer implements EventListenerObject {
130
130
ripple . style . backgroundColor = config . color ;
131
131
}
132
132
133
- ripple . style . transitionDuration = `${ duration } ms` ;
133
+ ripple . style . transitionDuration = `${ enterDuration } ms` ;
134
134
135
135
this . _containerElement . appendChild ( ripple ) ;
136
136
137
137
// By default the browser does not recalculate the styles of dynamically created
138
- // ripple elements. This is critical because then the `scale` would not animate properly.
139
- enforceStyleRecalculation ( ripple ) ;
138
+ // ripple elements. This is critical to ensure that the `scale` animates properly.
139
+ // We enforce a style recalculation by calling `getComputedStyle` and *accessing* a property.
140
+ // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
141
+ const computedStyles = window . getComputedStyle ( ripple ) ;
142
+ const transitionProperty = computedStyles . transitionProperty ;
140
143
141
- // We use a 3d transform here in order to avoid an issue in Safari where
142
- // the ripples aren't clipped when inside the shadow DOM (see #24028).
143
- ripple . style . transform = 'scale3d(1, 1, 1)' ;
144
+ // Note: We detect whether animation is forcibly disabled through CSS by the use
145
+ // of `transition: none`. This is technically unexpected since animations are
146
+ // controlled through the animation config, but this exists for backwards compatibility
147
+ const animationForciblyDisabledThroughCss = transitionProperty === 'none' ;
144
148
145
149
// Exposed reference to the ripple that will be returned.
146
- const rippleRef = new RippleRef ( this , ripple , config ) ;
150
+ const rippleRef = new RippleRef ( this , ripple , config , animationForciblyDisabledThroughCss ) ;
151
+
152
+ // Start the enter animation by setting the transform/scale to 100%. The animation will
153
+ // execute as part of this statement because we forced a style recalculation before.
154
+ // Note: We use a 3d transform here in order to avoid an issue in Safari where
155
+ // the ripples aren't clipped when inside the shadow DOM (see #24028).
156
+ ripple . style . transform = 'scale3d(1, 1, 1)' ;
147
157
148
158
rippleRef . state = RippleState . FADING_IN ;
149
159
@@ -156,15 +166,15 @@ export class RippleRenderer implements EventListenerObject {
156
166
157
167
// Do not register the `transition` event listener if fade-in and fade-out duration
158
168
// are set to zero. The events won't fire anyway and we can save resources here.
159
- if ( duration || animationConfig . exitDuration ) {
169
+ if ( ! animationForciblyDisabledThroughCss && ( enterDuration || animationConfig . exitDuration ) ) {
160
170
this . _ngZone . runOutsideAngular ( ( ) => {
161
171
ripple . addEventListener ( 'transitionend' , ( ) => this . _finishRippleTransition ( rippleRef ) ) ;
162
172
} ) ;
163
173
}
164
174
165
175
// In case there is no fade-in transition duration, we need to manually call the transition
166
176
// end listener because `transitionend` doesn't fire if there is no transition.
167
- if ( ! duration ) {
177
+ if ( animationForciblyDisabledThroughCss || ! enterDuration ) {
168
178
this . _finishRippleTransition ( rippleRef ) ;
169
179
}
170
180
@@ -200,7 +210,7 @@ export class RippleRenderer implements EventListenerObject {
200
210
201
211
// In case there is no fade-out transition duration, we need to manually call the
202
212
// transition end listener because `transitionend` doesn't fire if there is no transition.
203
- if ( ! animationConfig . exitDuration ) {
213
+ if ( rippleRef . _animationForciblyDisabledThroughCss || ! animationConfig . exitDuration ) {
204
214
this . _finishRippleTransition ( rippleRef ) ;
205
215
}
206
216
}
@@ -371,14 +381,6 @@ export class RippleRenderer implements EventListenerObject {
371
381
}
372
382
}
373
383
374
- /** Enforces a style recalculation of a DOM element by computing its styles. */
375
- function enforceStyleRecalculation ( element : HTMLElement ) {
376
- // Enforce a style recalculation by calling `getComputedStyle` and accessing any property.
377
- // Calling `getPropertyValue` is important to let optimizers know that this is not a noop.
378
- // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
379
- window . getComputedStyle ( element ) . getPropertyValue ( 'opacity' ) ;
380
- }
381
-
382
384
/**
383
385
* Returns the distance from the point (x, y) to the furthest corner of a rectangle.
384
386
*/
0 commit comments