diff --git a/src/components/navBar/navBar.js b/src/components/navBar/navBar.js index 68a455bf65..2264d6a4a3 100644 --- a/src/components/navBar/navBar.js +++ b/src/components/navBar/navBar.js @@ -104,6 +104,24 @@ function MdNavBar($mdAria, $mdTheming) { '' + '', link: function(scope, element, attrs, ctrl) { + + ctrl.width = $window.innerWidth; + + function onResize() { + if (ctrl.width !== $window.innerWidth) { + ctrl.updateSelectedTabInkBar(); + ctrl.width = $window.innerWidth; + scope.$digest(); + } + } + + function cleanUp() { + angular.element($window).off('resize', onResize); + } + + angular.element($window).on('resize', $mdUtil.debounce(onResize, 300)); + scope.$on('$destroy', cleanUp); + $mdTheming(element); if (!ctrl.navBarAriaLabel) { $mdAria.expectAsync(element, 'aria-label', angular.noop); @@ -229,20 +247,28 @@ MdNavBarController.prototype._updateTabs = function(newValue, oldValue) { * Repositions the ink bar to the selected tab. * @private */ -MdNavBarController.prototype._updateInkBarStyles = function(tab, newIndex, oldIndex) { - this._inkbar.toggleClass('_md-left', newIndex < oldIndex) - .toggleClass('_md-right', newIndex > oldIndex); - +MdNavBarController.prototype._updateInkBarStyles = function(tab, newIndex) { this._inkbar.css({display: newIndex < 0 ? 'none' : ''}); if (tab) { var tabEl = tab.getButtonEl(); var left = tabEl.offsetLeft; + var tabWidth = tabEl.offsetWidth; + var navBarWidth = this._navBarEl.getBoundingClientRect().width; + var scale = tabWidth / navBarWidth; + var translate = left / navBarWidth * 100; - this._inkbar.css({left: left + 'px', width: tabEl.offsetWidth + 'px'}); + this._inkbar.css({ transform: 'translateX(' + translate + '%) scaleX(' + scale + ')' }); } }; +/** + * Updates inkbar to match current tab. + */ +MdNavBarController.prototype.updateSelectedTabInkBar = function() { + this._updateInkBarStyles(this._getSelectedTab()); +} + /** * Returns an array of the current tabs. * @return {Array} diff --git a/src/components/navBar/navBar.scss b/src/components/navBar/navBar.scss index 36a7b34b6e..914c2ec3ce 100644 --- a/src/components/navBar/navBar.scss +++ b/src/components/navBar/navBar.scss @@ -39,21 +39,15 @@ $md-nav-bar-height: 48px; md-nav-ink-bar { $duration: $swift-ease-in-out-duration * 0.5; $multiplier: 0.5; + background-color: black; + position: absolute; bottom: 0; + left: 0; + width: 100%; height: 2px; - left: auto; - position: absolute; - right: auto; - background-color: black; - - &._md-left { - transition: left ($duration * $multiplier) $swift-ease-in-out-timing-function, - right $duration $swift-ease-in-out-timing-function; - } - &._md-right { - transition: left $duration $swift-ease-in-out-timing-function, - right ($duration * $multiplier) $swift-ease-in-out-timing-function; - } + transform-origin: left top; + will-change: transform; + transition: transform ($duration * $multiplier) $swift-ease-in-out-timing-function; // By default $ngAnimate looks for transition durations on the element, when using ng-hide, ng-if, ng-show. // The ink bar has a transition duration applied, which means, that $ngAnimate delays the hide process. diff --git a/src/components/navBar/navBar.spec.js b/src/components/navBar/navBar.spec.js index c614933d3e..4727520a18 100644 --- a/src/components/navBar/navBar.spec.js +++ b/src/components/navBar/navBar.spec.js @@ -261,15 +261,25 @@ describe('mdNavBar', function() { $scope.selectedTabRoute = 'tab1'; createTabs(); + var tabLeft = getTab('tab1')[0].offsetLeft; + var inkbarTranslate = parseFloat(getInkbarEl().style.transform.match(/\d+\.\d+/g)[0]); + var elWidth = el[0].getBoundingClientRect().width; + + var translate = tabLeft / elWidth * 100; // b/c there is no css in the karma test, we have to interrogate the // inkbar style property directly - expect(parseInt(getInkbarEl().style.left)) - .toBeCloseTo(getTab('tab1')[0].offsetLeft, 0.1); + expect(inkbarTranslate) + .toBeCloseTo(translate, 1); updateSelectedTabRoute('tab3'); - expect(parseInt(getInkbarEl().style.left)) - .toBeCloseTo(getTab('tab3')[0].offsetLeft, 0.1); + tabLeft = getTab('tab3')[0].offsetLeft + inkbarTranslate = parseFloat(getInkbarEl().style.transform.match(/\d+\.\d+/g)[0]); + elWidth = el[0].getBoundingClientRect().width; + translate = tabLeft / elWidth * 100; + + expect(inkbarTranslate) + .toBeCloseTo(translate, 1); }); it('should hide if md-no-ink-bar is enabled', function() {