diff --git a/src/lib/core/style/_noop-animation.scss b/src/lib/core/style/_noop-animation.scss new file mode 100644 index 00000000000..f1f3131b04b --- /dev/null +++ b/src/lib/core/style/_noop-animation.scss @@ -0,0 +1,21 @@ +// If the mat-animation-noop class is present on the components root element, +// prevent non css animations from running. +// NOTE: Currently this mixin should only be used with components that do not +// have any projected content. +@mixin _noop-animation() { + // @at-root is used to steps outside of the hierarchy of the scss rules. This is + // done to allow a class to be added to be added to base of the scss nesting + // context. + // For example: + // .my-root { + // .my-subclass { + // @include _noop-animation() + // } + // } + // results in: + // ._mat-animation-noopable.my-root .my-subclass { ... } + @at-root ._mat-animation-noopable#{&} { + transition: none; + animation: none; + } +} diff --git a/src/lib/progress-bar/progress-bar.scss b/src/lib/progress-bar/progress-bar.scss index d1e1e2df37e..e6514dcc317 100644 --- a/src/lib/progress-bar/progress-bar.scss +++ b/src/lib/progress-bar/progress-bar.scss @@ -1,5 +1,6 @@ @import '../core/style/variables'; @import '../core/style/vendor-prefixes'; +@import '../core/style/noop-animation'; $mat-progress-bar-height: 5px !default; $mat-progress-bar-full-animation-duration: 2000ms !default; @@ -7,6 +8,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; .mat-progress-bar { + @include _noop-animation(); display: block; // Height is provided for mat-progress-bar to act as a default. height: $mat-progress-bar-height; @@ -33,6 +35,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; // The progress bar buffer is the bar indicator showing the buffer value and is only visible // beyond the current value of the primary progress bar. .mat-progress-bar-buffer { + @include _noop-animation(); transform-origin: top left; transition: transform $mat-progress-bar-piece-animation-duration ease; } @@ -45,6 +48,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; // The progress bar fill fills the progress bar with the indicator color. .mat-progress-bar-fill { + @include _noop-animation(); animation: none; transform-origin: top left; transition: transform $mat-progress-bar-piece-animation-duration ease; @@ -52,6 +56,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; // A pseudo element is created for each progress bar bar that fills with the indicator color. .mat-progress-bar-fill::after { + @include _noop-animation(); animation: none; content: ''; display: inline-block; @@ -76,10 +81,12 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; &[mode='indeterminate'], &[mode='query'] { .mat-progress-bar-fill { + @include _noop-animation(); transition: none; } .mat-progress-bar-primary { // Avoids stacked animation tearing in Firefox >= 57. + @include _noop-animation(); @include backface-visibility(hidden); animation: mat-progress-bar-primary-indeterminate-translate $mat-progress-bar-full-animation-duration infinite linear; @@ -87,12 +94,14 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; } .mat-progress-bar-primary.mat-progress-bar-fill::after { // Avoids stacked animation tearing in Firefox >= 57. + @include _noop-animation(); @include backface-visibility(hidden); animation: mat-progress-bar-primary-indeterminate-scale $mat-progress-bar-full-animation-duration infinite linear; } .mat-progress-bar-secondary { // Avoids stacked animation tearing in Firefox >= 57. + @include _noop-animation(); @include backface-visibility(hidden); animation: mat-progress-bar-secondary-indeterminate-translate $mat-progress-bar-full-animation-duration infinite linear; @@ -101,6 +110,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; } .mat-progress-bar-secondary.mat-progress-bar-fill::after { // Avoids stacked animation tearing in Firefox >= 57. + @include _noop-animation(); @include backface-visibility(hidden); animation: mat-progress-bar-secondary-indeterminate-scale $mat-progress-bar-full-animation-duration infinite linear; @@ -110,6 +120,7 @@ $mat-progress-bar-piece-animation-duration: 250ms !default; &[mode='buffer'] { .mat-progress-bar-background { // Avoids stacked animation tearing in Firefox >= 57. + @include _noop-animation(); @include backface-visibility(hidden); animation: mat-progress-bar-background-scroll $mat-progress-bar-piece-animation-duration infinite linear; diff --git a/src/lib/progress-bar/progress-bar.ts b/src/lib/progress-bar/progress-bar.ts index 6231ebda849..d12f50243da 100644 --- a/src/lib/progress-bar/progress-bar.ts +++ b/src/lib/progress-bar/progress-bar.ts @@ -9,9 +9,12 @@ import { Component, ChangeDetectionStrategy, ElementRef, + Inject, Input, + Optional, ViewEncapsulation } from '@angular/core'; +import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations'; import {CanColor, mixinColor} from '@angular/material/core'; // TODO(josephperrott): Benchpress tests. @@ -42,6 +45,7 @@ let progressbarId = 0; '[attr.aria-valuenow]': 'value', '[attr.mode]': 'mode', 'class': 'mat-progress-bar', + '[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`, }, inputs: ['color'], templateUrl: 'progress-bar.html', @@ -51,7 +55,9 @@ let progressbarId = 0; }) export class MatProgressBar extends _MatProgressBarMixinBase implements CanColor { - constructor(public _elementRef: ElementRef) { + + constructor(public _elementRef: ElementRef, + @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string) { super(_elementRef); } diff --git a/src/lib/progress-spinner/progress-spinner.scss b/src/lib/progress-spinner/progress-spinner.scss index c20e256d6f5..b0a75766af5 100644 --- a/src/lib/progress-spinner/progress-spinner.scss +++ b/src/lib/progress-spinner/progress-spinner.scss @@ -1,4 +1,5 @@ @import '../core/style/variables'; +@import '../core/style/noop-animation'; // Animation config @@ -22,16 +23,19 @@ $_mat-progress-spinner-default-circumference: $pi * $_mat-progress-spinner-defau } circle { + @include _noop-animation(); fill: transparent; transform-origin: center; transition: stroke-dashoffset 225ms linear; } &.mat-progress-spinner-indeterminate-animation[mode='indeterminate'] { + @include _noop-animation(); animation: mat-progress-spinner-linear-rotate $swift-ease-in-out-duration * 4 linear infinite; circle { + @include _noop-animation(); transition-property: stroke; // Note: we multiply the duration by 8, because the animation is spread out in 8 stages. animation-duration: $swift-ease-in-out-duration * 8; @@ -41,12 +45,14 @@ $_mat-progress-spinner-default-circumference: $pi * $_mat-progress-spinner-defau } &.mat-progress-spinner-indeterminate-fallback-animation[mode='indeterminate'] { + @include _noop-animation(); animation: mat-progress-spinner-stroke-rotate-fallback $mat-progress-spinner-stroke-rotate-fallback-duration $mat-progress-spinner-stroke-rotate-fallback-ease infinite; circle { + @include _noop-animation(); transition-property: stroke; } } diff --git a/src/lib/progress-spinner/progress-spinner.ts b/src/lib/progress-spinner/progress-spinner.ts index dc7b88885c3..7d4bb6abaae 100644 --- a/src/lib/progress-spinner/progress-spinner.ts +++ b/src/lib/progress-spinner/progress-spinner.ts @@ -9,12 +9,13 @@ import { Component, ChangeDetectionStrategy, + Inject, Input, ElementRef, ViewEncapsulation, Optional, - Inject, } from '@angular/core'; +import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations'; import {CanColor, mixinColor} from '@angular/material/core'; import {Platform} from '@angular/cdk/platform'; import {DOCUMENT} from '@angular/common'; @@ -80,6 +81,7 @@ const INDETERMINATE_ANIMATION_TEMPLATE = ` host: { 'role': 'progressbar', 'class': 'mat-progress-spinner', + '[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`, '[style.width.px]': 'diameter', '[style.height.px]': 'diameter', '[attr.aria-valuemin]': 'mode === "determinate" ? 0 : null', @@ -144,7 +146,8 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements constructor(public _elementRef: ElementRef, platform: Platform, - @Optional() @Inject(DOCUMENT) private _document: any) { + @Optional() @Inject(DOCUMENT) private _document: any, + @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string) { super(_elementRef); this._fallbackAnimation = platform.EDGE || platform.TRIDENT; @@ -233,6 +236,7 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements 'role': 'progressbar', 'mode': 'indeterminate', 'class': 'mat-spinner mat-progress-spinner', + '[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`, '[style.width.px]': 'diameter', '[style.height.px]': 'diameter', }, @@ -244,8 +248,9 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements }) export class MatSpinner extends MatProgressSpinner { constructor(elementRef: ElementRef, platform: Platform, - @Optional() @Inject(DOCUMENT) document: any) { - super(elementRef, platform, document); + @Optional() @Inject(DOCUMENT) document: any, + @Optional() @Inject(ANIMATION_MODULE_TYPE) _animationMode?: string) { + super(elementRef, platform, document, _animationMode); this.mode = 'indeterminate'; } }