@angular/material
Version:
Angular Material
475 lines (474 loc) • 19.2 kB
JavaScript
import * as tslib_1 from "tslib";
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { ChangeDetectionStrategy, Component, Directive, ElementRef, Input, NgModule, NgZone, Renderer2, ViewChild, ViewEncapsulation } from '@angular/core';
import { MdCommonModule, mixinColor } from '@angular/material/core';
/**
* A single degree in radians.
*/
var DEGREE_IN_RADIANS = Math.PI / 180;
/**
* Duration of the indeterminate animation.
*/
var DURATION_INDETERMINATE = 667;
/**
* Duration of the indeterminate animation.
*/
var DURATION_DETERMINATE = 225;
/**
* Start animation value of the indeterminate animation
*/
var startIndeterminate = 3;
/**
* End animation value of the indeterminate animation
*/
var endIndeterminate = 80;
/**
* Maximum angle for the arc. The angle can't be exactly 360, because the arc becomes hidden.
*/
var MAX_ANGLE = 359.99 / 100;
/**
* Whether the user's browser supports requestAnimationFrame.
*/
var HAS_RAF = typeof requestAnimationFrame !== 'undefined';
/**
* Default stroke width as a percentage of the viewBox.
*/
var PROGRESS_SPINNER_STROKE_WIDTH = 10;
/**
* Directive whose purpose is to add the mat- CSS styling to this selector.
* \@docs-private
*/
var MdProgressSpinnerCssMatStyler = (function () {
function MdProgressSpinnerCssMatStyler() {
}
return MdProgressSpinnerCssMatStyler;
}());
MdProgressSpinnerCssMatStyler.decorators = [
{ type: Directive, args: [{
selector: 'md-progress-spinner, mat-progress-spinner',
host: { 'class': 'mat-progress-spinner' }
},] },
];
/**
* @nocollapse
*/
MdProgressSpinnerCssMatStyler.ctorParameters = function () { return []; };
/**
* \@docs-private
*/
var MdProgressSpinnerBase = (function () {
/**
* @param {?} _renderer
* @param {?} _elementRef
*/
function MdProgressSpinnerBase(_renderer, _elementRef) {
this._renderer = _renderer;
this._elementRef = _elementRef;
}
return MdProgressSpinnerBase;
}());
var _MdProgressSpinnerMixinBase = mixinColor(MdProgressSpinnerBase, 'primary');
/**
* <md-progress-spinner> component.
*/
var MdProgressSpinner = (function (_super) {
tslib_1.__extends(MdProgressSpinner, _super);
/**
* @param {?} renderer
* @param {?} elementRef
* @param {?} _ngZone
*/
function MdProgressSpinner(renderer, elementRef, _ngZone) {
var _this = _super.call(this, renderer, elementRef) || this;
_this._ngZone = _ngZone;
/**
* The id of the last requested animation.
*/
_this._lastAnimationId = 0;
_this._mode = 'determinate';
/**
* Stroke width of the progress spinner. By default uses 10px as stroke width.
*/
_this.strokeWidth = PROGRESS_SPINNER_STROKE_WIDTH;
return _this;
}
Object.defineProperty(MdProgressSpinner.prototype, "_ariaValueMin", {
/**
* Values for aria max and min are only defined as numbers when in a determinate mode. We do this
* because voiceover does not report the progress indicator as indeterminate if the aria min
* and/or max value are number values.
* @return {?}
*/
get: function () {
return this.mode == 'determinate' ? 0 : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MdProgressSpinner.prototype, "_ariaValueMax", {
/**
* @return {?}
*/
get: function () {
return this.mode == 'determinate' ? 100 : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MdProgressSpinner.prototype, "interdeterminateInterval", {
/**
* \@docs-private
* @return {?}
*/
get: function () {
return this._interdeterminateInterval;
},
/**
* \@docs-private
* @param {?} interval
* @return {?}
*/
set: function (interval) {
if (this._interdeterminateInterval) {
clearInterval(this._interdeterminateInterval);
}
this._interdeterminateInterval = interval;
},
enumerable: true,
configurable: true
});
/**
* Clean up any animations that were running.
* @return {?}
*/
MdProgressSpinner.prototype.ngOnDestroy = function () {
this._cleanupIndeterminateAnimation();
};
Object.defineProperty(MdProgressSpinner.prototype, "value", {
/**
* Value of the progress circle. It is bound to the host as the attribute aria-valuenow.
* @return {?}
*/
get: function () {
if (this.mode == 'determinate') {
return this._value;
}
return 0;
},
/**
* @param {?} v
* @return {?}
*/
set: function (v) {
if (v != null && this.mode == 'determinate') {
var /** @type {?} */ newValue = clamp(v);
this._animateCircle(this.value || 0, newValue);
this._value = newValue;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MdProgressSpinner.prototype, "mode", {
/**
* Mode of the progress circle
*
* Input must be one of the values from ProgressMode, defaults to 'determinate'.
* mode is bound to the host as the attribute host.
* @return {?}
*/
get: function () { return this._mode; },
/**
* @param {?} mode
* @return {?}
*/
set: function (mode) {
if (mode !== this._mode) {
if (mode === 'indeterminate') {
this._startIndeterminateAnimation();
}
else {
this._cleanupIndeterminateAnimation();
this._animateCircle(0, this._value);
}
this._mode = mode;
}
},
enumerable: true,
configurable: true
});
/**
* Animates the circle from one percentage value to another.
*
* @param {?} animateFrom The percentage of the circle filled starting the animation.
* @param {?} animateTo The percentage of the circle filled ending the animation.
* @param {?=} ease The easing function to manage the pace of change in the animation.
* @param {?=} duration The length of time to show the animation, in milliseconds.
* @param {?=} rotation The starting angle of the circle fill, with 0° represented at the top center
* of the circle.
* @return {?}
*/
MdProgressSpinner.prototype._animateCircle = function (animateFrom, animateTo, ease, duration, rotation) {
var _this = this;
if (ease === void 0) { ease = linearEase; }
if (duration === void 0) { duration = DURATION_DETERMINATE; }
if (rotation === void 0) { rotation = 0; }
var /** @type {?} */ id = ++this._lastAnimationId;
var /** @type {?} */ startTime = Date.now();
var /** @type {?} */ changeInValue = animateTo - animateFrom;
// No need to animate it if the values are the same
if (animateTo === animateFrom) {
this._renderArc(animateTo, rotation);
}
else {
var /** @type {?} */ animation_1 = function () {
// If there is no requestAnimationFrame, skip ahead to the end of the animation.
var /** @type {?} */ elapsedTime = HAS_RAF ?
Math.max(0, Math.min(Date.now() - startTime, duration)) :
duration;
_this._renderArc(ease(elapsedTime, animateFrom, changeInValue, duration), rotation);
// Prevent overlapping animations by checking if a new animation has been called for and
// if the animation has lasted longer than the animation duration.
if (id === _this._lastAnimationId && elapsedTime < duration) {
requestAnimationFrame(animation_1);
}
};
// Run the animation outside of Angular's zone, in order to avoid
// hitting ZoneJS and change detection on each frame.
this._ngZone.runOutsideAngular(animation_1);
}
};
/**
* Starts the indeterminate animation interval, if it is not already running.
* @return {?}
*/
MdProgressSpinner.prototype._startIndeterminateAnimation = function () {
var _this = this;
var /** @type {?} */ rotationStartPoint = 0;
var /** @type {?} */ start = startIndeterminate;
var /** @type {?} */ end = endIndeterminate;
var /** @type {?} */ duration = DURATION_INDETERMINATE;
var /** @type {?} */ animate = function () {
_this._animateCircle(start, end, materialEase, duration, rotationStartPoint);
// Prevent rotation from reaching Number.MAX_SAFE_INTEGER.
rotationStartPoint = (rotationStartPoint + end) % 100;
var /** @type {?} */ temp = start;
start = -end;
end = -temp;
};
if (!this.interdeterminateInterval) {
this._ngZone.runOutsideAngular(function () {
_this.interdeterminateInterval = setInterval(animate, duration + 50, 0, false);
animate();
});
}
};
/**
* Removes interval, ending the animation.
* @return {?}
*/
MdProgressSpinner.prototype._cleanupIndeterminateAnimation = function () {
this.interdeterminateInterval = null;
};
/**
* Renders the arc onto the SVG element. Proxies `getArc` while setting the proper
* DOM attribute on the `<path>`.
* @param {?} currentValue
* @param {?=} rotation
* @return {?}
*/
MdProgressSpinner.prototype._renderArc = function (currentValue, rotation) {
if (rotation === void 0) { rotation = 0; }
if (this._path) {
var /** @type {?} */ svgArc = getSvgArc(currentValue, rotation, this.strokeWidth);
this._renderer.setAttribute(this._path.nativeElement, 'd', svgArc);
}
};
return MdProgressSpinner;
}(_MdProgressSpinnerMixinBase));
MdProgressSpinner.decorators = [
{ type: Component, args: [{ selector: 'md-progress-spinner, mat-progress-spinner',
host: {
'role': 'progressbar',
'class': 'mat-progress-spinner',
'[attr.aria-valuemin]': '_ariaValueMin',
'[attr.aria-valuemax]': '_ariaValueMax',
'[attr.aria-valuenow]': 'value',
'[attr.mode]': 'mode',
},
inputs: ['color'],
template: "<svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid meet\" focusable=\"false\"><path #path [style.strokeWidth]=\"strokeWidth\"></path></svg>",
styles: [".mat-progress-spinner{display:block;height:100px;width:100px;overflow:hidden}.mat-progress-spinner svg{height:100%;width:100%;transform-origin:center}.mat-progress-spinner path{fill:transparent;transition:stroke .3s cubic-bezier(.35,0,.25,1)}.mat-progress-spinner[mode=indeterminate] svg{animation-duration:5.25s,2.887s;animation-name:mat-progress-spinner-sporadic-rotate,mat-progress-spinner-linear-rotate;animation-timing-function:cubic-bezier(.35,0,.25,1),linear;animation-iteration-count:infinite;transition:none}@keyframes mat-progress-spinner-linear-rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes mat-progress-spinner-sporadic-rotate{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}100%{transform:rotate(1080deg)}}"],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
},] },
];
/**
* @nocollapse
*/
MdProgressSpinner.ctorParameters = function () { return [
{ type: Renderer2, },
{ type: ElementRef, },
{ type: NgZone, },
]; };
MdProgressSpinner.propDecorators = {
'_path': [{ type: ViewChild, args: ['path',] },],
'strokeWidth': [{ type: Input },],
'value': [{ type: Input },],
'mode': [{ type: Input },],
};
/**
* <md-spinner> component.
*
* This is a component definition to be used as a convenience reference to create an
* indeterminate <md-progress-spinner> instance.
*/
var MdSpinner = (function (_super) {
tslib_1.__extends(MdSpinner, _super);
/**
* @param {?} elementRef
* @param {?} ngZone
* @param {?} renderer
*/
function MdSpinner(elementRef, ngZone, renderer) {
var _this = _super.call(this, renderer, elementRef, ngZone) || this;
_this.mode = 'indeterminate';
return _this;
}
return MdSpinner;
}(MdProgressSpinner));
MdSpinner.decorators = [
{ type: Component, args: [{ selector: 'md-spinner, mat-spinner',
host: {
'role': 'progressbar',
'mode': 'indeterminate',
'class': 'mat-spinner mat-progress-spinner',
},
inputs: ['color'],
template: "<svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid meet\" focusable=\"false\"><path #path [style.strokeWidth]=\"strokeWidth\"></path></svg>",
styles: [".mat-progress-spinner{display:block;height:100px;width:100px;overflow:hidden}.mat-progress-spinner svg{height:100%;width:100%;transform-origin:center}.mat-progress-spinner path{fill:transparent;transition:stroke .3s cubic-bezier(.35,0,.25,1)}.mat-progress-spinner[mode=indeterminate] svg{animation-duration:5.25s,2.887s;animation-name:mat-progress-spinner-sporadic-rotate,mat-progress-spinner-linear-rotate;animation-timing-function:cubic-bezier(.35,0,.25,1),linear;animation-iteration-count:infinite;transition:none}@keyframes mat-progress-spinner-linear-rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes mat-progress-spinner-sporadic-rotate{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}100%{transform:rotate(1080deg)}}"],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
},] },
];
/**
* @nocollapse
*/
MdSpinner.ctorParameters = function () { return [
{ type: ElementRef, },
{ type: NgZone, },
{ type: Renderer2, },
]; };
/**
* Clamps a value to be between 0 and 100.
* @param {?} v
* @return {?}
*/
function clamp(v) {
return Math.max(0, Math.min(100, v));
}
/**
* Converts Polar coordinates to Cartesian.
* @param {?} radius
* @param {?} pathRadius
* @param {?} angleInDegrees
* @return {?}
*/
function polarToCartesian(radius, pathRadius, angleInDegrees) {
var /** @type {?} */ angleInRadians = (angleInDegrees - 90) * DEGREE_IN_RADIANS;
return (radius + (pathRadius * Math.cos(angleInRadians))) +
',' + (radius + (pathRadius * Math.sin(angleInRadians)));
}
/**
* Easing function for linear animation.
* @param {?} currentTime
* @param {?} startValue
* @param {?} changeInValue
* @param {?} duration
* @return {?}
*/
function linearEase(currentTime, startValue, changeInValue, duration) {
return changeInValue * currentTime / duration + startValue;
}
/**
* Easing function to match material design indeterminate animation.
* @param {?} currentTime
* @param {?} startValue
* @param {?} changeInValue
* @param {?} duration
* @return {?}
*/
function materialEase(currentTime, startValue, changeInValue, duration) {
var /** @type {?} */ time = currentTime / duration;
var /** @type {?} */ timeCubed = Math.pow(time, 3);
var /** @type {?} */ timeQuad = Math.pow(time, 4);
var /** @type {?} */ timeQuint = Math.pow(time, 5);
return startValue + changeInValue * ((6 * timeQuint) + (-15 * timeQuad) + (10 * timeCubed));
}
/**
* Determines the path value to define the arc. Converting percentage values to to polar
* coordinates on the circle, and then to cartesian coordinates in the viewport.
*
* @param {?} currentValue The current percentage value of the progress circle, the percentage of the
* circle to fill.
* @param {?} rotation The starting point of the circle with 0 being the 0 degree point.
* @param {?} strokeWidth Stroke width of the progress spinner arc.
* @return {?} A string for an SVG path representing a circle filled from the starting point to the
* percentage value provided.
*/
function getSvgArc(currentValue, rotation, strokeWidth) {
var /** @type {?} */ startPoint = rotation || 0;
var /** @type {?} */ radius = 50;
var /** @type {?} */ pathRadius = radius - strokeWidth;
var /** @type {?} */ startAngle = startPoint * MAX_ANGLE;
var /** @type {?} */ endAngle = currentValue * MAX_ANGLE;
var /** @type {?} */ start = polarToCartesian(radius, pathRadius, startAngle);
var /** @type {?} */ end = polarToCartesian(radius, pathRadius, endAngle + startAngle);
var /** @type {?} */ arcSweep = endAngle < 0 ? 0 : 1;
var /** @type {?} */ largeArcFlag;
if (endAngle < 0) {
largeArcFlag = endAngle >= -180 ? 0 : 1;
}
else {
largeArcFlag = endAngle <= 180 ? 0 : 1;
}
return "M" + start + "A" + pathRadius + "," + pathRadius + " 0 " + largeArcFlag + "," + arcSweep + " " + end;
}
var MdProgressSpinnerModule = (function () {
function MdProgressSpinnerModule() {
}
return MdProgressSpinnerModule;
}());
MdProgressSpinnerModule.decorators = [
{ type: NgModule, args: [{
imports: [MdCommonModule],
exports: [
MdProgressSpinner,
MdSpinner,
MdCommonModule,
MdProgressSpinnerCssMatStyler
],
declarations: [
MdProgressSpinner,
MdSpinner,
MdProgressSpinnerCssMatStyler
],
},] },
];
/**
* @nocollapse
*/
MdProgressSpinnerModule.ctorParameters = function () { return []; };
/**
* Generated bundle index. Do not edit.
*/
export { MdProgressSpinnerModule, PROGRESS_SPINNER_STROKE_WIDTH, MdProgressSpinnerCssMatStyler, MdProgressSpinnerBase, _MdProgressSpinnerMixinBase, MdProgressSpinner, MdSpinner, MdProgressSpinner as MatProgressSpinner, MdProgressSpinnerBase as MatProgressSpinnerBase, MdProgressSpinnerCssMatStyler as MatProgressSpinnerCssMatStyler, MdProgressSpinnerModule as MatProgressSpinnerModule, MdSpinner as MatSpinner };
//# sourceMappingURL=progress-spinner.es5.js.map