diff --git a/src/components/panel/demoPanelAnimations/index.html b/src/components/panel/demoPanelAnimations/index.html index 5142dc17f16..22dacc1d8a1 100644 --- a/src/components/panel/demoPanelAnimations/index.html +++ b/src/components/panel/demoPanelAnimations/index.html @@ -1,8 +1,8 @@

Animations

-
- OpenFrom: +
+

OpenFrom:

Button Top/Left Corner @@ -10,8 +10,8 @@

Animations

-
- CloseTo: +
+

CloseTo:

Button Top/Left Corner @@ -19,8 +19,8 @@

Animations

-
- AnimationType: +
+

AnimationType:

None Slide @@ -29,6 +29,33 @@

Animations

Custom
+ +
+

Duration:

+ + + + + + + + + + + + + + +
diff --git a/src/components/panel/demoPanelAnimations/script.js b/src/components/panel/demoPanelAnimations/script.js index 5632b597f7f..1731a80a267 100644 --- a/src/components/panel/demoPanelAnimations/script.js +++ b/src/components/panel/demoPanelAnimations/script.js @@ -10,7 +10,12 @@ function AnimationCtrl($mdPanel) { this._mdPanel = $mdPanel; this.openFrom = 'button'; this.closeTo = 'button'; - this.animationType = 'none'; + this.animationType = 'scale'; + this.duration = 300; + this.separateDurations = { + open: this.duration, + close: this.duration + }; } @@ -22,6 +27,8 @@ AnimationCtrl.prototype.showDialog = function() { var animation = this._mdPanel.newPanelAnimation(); + animation.duration(this.duration || this.separateDurations); + switch(this.openFrom) { case 'button': animation.openFrom('.animation-target'); diff --git a/src/components/panel/panel.js b/src/components/panel/panel.js index c4d02a70ec9..8a02c9edaad 100644 --- a/src/components/panel/panel.js +++ b/src/components/panel/panel.js @@ -592,24 +592,27 @@ angular * MdPanelAnimation * *****************************************************************************/ - /** * @ngdoc type * @name MdPanelAnimation + * @module material.components.panel * @description * Animation configuration object. To use, create an MdPanelAnimation with the * desired properties, then pass the object as part of $mdPanel creation. * - * Example: + * @usage * + * * var panelAnimation = new MdPanelAnimation() * .openFrom(myButtonEl) + * .duration(1337) * .closeTo('.my-button') * .withAnimation($mdPanel.animation.SCALE); * * $mdPanel.create({ * animation: panelAnimation * }); + * */ /** @@ -658,6 +661,18 @@ angular * @returns {!MdPanelAnimation} */ +/** + * @ngdoc method + * @name MdPanelAnimation#duration + * @description + * Specifies the duration of the animation in milliseconds. The `duration` + * method accepts either a number or an object with separate open and close + * durations. + * + * @param {number|{open: number, close: number}} duration + * @returns {!MdPanelAnimation} + */ + /***************************************************************************** * IMPLEMENTATION * @@ -1399,6 +1414,11 @@ MdPanelRef.prototype._createBackdrop = function() { open: '_md-opaque-enter', close: '_md-opaque-leave' }); + + if (this.config.animation) { + backdropAnimation.duration(this.config.animation._rawDuration); + } + var backdropConfig = { animation: backdropAnimation, attachTo: this.config.attachTo, @@ -1406,6 +1426,7 @@ MdPanelRef.prototype._createBackdrop = function() { panelClass: '_md-panel-backdrop', zIndex: this.config.zIndex - 1 }; + this._backdropRef = this._$mdPanel.create(backdropConfig); } if (!this._backdropRef.isAttached) { @@ -1543,7 +1564,7 @@ MdPanelRef.prototype._configureScrollListener = function() { * @private */ MdPanelRef.prototype._configureTrapFocus = function() { - // Focus doesn't remain instead of the panel without this. + // Focus doesn't remain inside of the panel without this. this.panelEl.attr('tabIndex', '-1'); if (this.config['trapFocus']) { var element = this.panelEl; @@ -2279,6 +2300,15 @@ function MdPanelAnimation($injector) { /** @private {string|{open: string, close: string}} */ this._animationClass = ''; + + /** @private {number} */ + this._openDuration; + + /** @private {number} */ + this._closeDuration; + + /** @private {number|{open: number, close: number}} */ + this._rawDuration; } @@ -2326,6 +2356,30 @@ MdPanelAnimation.prototype.closeTo = function(closeTo) { return this; }; +/** + * Specifies the duration of the animation in milliseconds. + * @param {number|{open: number, close: number}} duration + * @returns {!MdPanelAnimation} + */ +MdPanelAnimation.prototype.duration = function(duration) { + if (duration) { + if (angular.isNumber(duration)) { + this._openDuration = this._closeDuration = toSeconds(duration); + } else if (angular.isObject(duration)) { + this._openDuration = toSeconds(duration.open); + this._closeDuration = toSeconds(duration.close); + } + } + + // Save the original value so it can be passed to the backdrop. + this._rawDuration = duration; + + return this; + + function toSeconds(value) { + if (angular.isNumber(value)) return value / 1000; + } +}; /** * Returns the element and bounds for the animation target. @@ -2428,6 +2482,8 @@ MdPanelAnimation.prototype.animateOpen = function(panelEl) { } } + animationOptions.duration = this._openDuration; + return animator .translate3d(panelEl, openFrom, openTo, animationOptions); }; @@ -2491,6 +2547,8 @@ MdPanelAnimation.prototype.animateClose = function(panelEl) { } } + reverseAnimationOptions.duration = this._closeDuration; + return animator .translate3d(panelEl, closeFrom, closeTo, reverseAnimationOptions); }; diff --git a/src/components/panel/panel.spec.js b/src/components/panel/panel.spec.js index 208f36210d5..085590edf0d 100644 --- a/src/components/panel/panel.spec.js +++ b/src/components/panel/panel.spec.js @@ -2149,6 +2149,38 @@ describe('$mdPanel', function() { expect(animation._closeTo.bounds).toEqual(inputRect); }); }); + + describe('should determine the animation duration when', function() { + it('provided a value in milliseconds', function() { + var animation = mdPanelAnimation.duration(1300); + + expect(animation._openDuration).toBe(1.3); + }); + + it('provided a number', function() { + var animation = mdPanelAnimation.duration(2000); + + expect(animation._openDuration).toEqual(animation._closeDuration); + expect(animation._openDuration).toBe(2); + }); + + it('provided an object', function() { + var animation = mdPanelAnimation.duration({ + open: 1200, + close: 600 + }); + + expect(animation._openDuration).toBe(1.2); + expect(animation._closeDuration).toBe(0.6); + }); + + it('provided an invalid value', function() { + var animation = mdPanelAnimation.duration('very fast'); + + expect(animation._openDuration).toBeFalsy(); + expect(animation._closeDuration).toBeFalsy(); + }); + }); }); /** diff --git a/src/core/util/animation/animate.js b/src/core/util/animation/animate.js index ff0d455d281..96322a49211 100644 --- a/src/core/util/animation/animate.js +++ b/src/core/util/animation/animate.js @@ -21,11 +21,12 @@ function AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss) { * */ translate3d : function( target, from, to, options ) { - return $animateCss(target,{ - from:from, - to:to, - addClass:options.transitionInClass, - removeClass:options.transitionOutClass + return $animateCss(target, { + from: from, + to: to, + addClass: options.transitionInClass, + removeClass: options.transitionOutClass, + duration: options.duration }) .start() .then(function(){ @@ -40,7 +41,8 @@ function AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss) { return $animateCss(target, { to: newFrom || from, addClass: options.transitionOutClass, - removeClass: options.transitionInClass + removeClass: options.transitionInClass, + duration: options.duration }).start(); }