diff --git a/ionic/animations/animation.js b/ionic/animations/animation.js index ce137a7e21..22a4447613 100644 --- a/ionic/animations/animation.js +++ b/ionic/animations/animation.js @@ -239,15 +239,33 @@ export class Animation { this._hasFinished = true; var i, j, ele; - for (i = 0; i < this._el.length; i++) { - ele = this._el[i]; - for (j = 0; j < this._afterAddCls.length; j++) { - ele.classList.add(this._afterAddCls[j]); + if (this.playbackRate() < 0) { + // reverse direction + for (i = 0; i < this._el.length; i++) { + ele = this._el[i]; + + for (j = 0; j < this._beforeAddCls.length; j++) { + ele.classList.remove(this._beforeAddCls[j]); + } + + for (j = 0; j < this._beforeRmvCls.length; j++) { + ele.classList.add(this._beforeRmvCls[j]); + } } - for (j = 0; j < this._afterRmvCls.length; j++) { - ele.classList.remove(this._afterRmvCls[j]); + } else { + // normal direction + for (i = 0; i < this._el.length; i++) { + ele = this._el[i]; + + for (j = 0; j < this._afterAddCls.length; j++) { + ele.classList.add(this._afterAddCls[j]); + } + + for (j = 0; j < this._afterRmvCls.length; j++) { + ele.classList.remove(this._afterRmvCls[j]); + } } } @@ -293,8 +311,7 @@ class Animate { this.player = ele.animate([fromEffect, toEffect], { duration: duration, easing: easing, - playbackRate: playbackRate || 1, - fill: 'both' + playbackRate: playbackRate || 1 }); this.promise = new Promise(resolve => { diff --git a/ionic/components/content/swipe-handle.js b/ionic/components/content/swipe-handle.js index ab05ad0ee3..08f1bdea32 100644 --- a/ionic/components/content/swipe-handle.js +++ b/ionic/components/content/swipe-handle.js @@ -21,47 +21,51 @@ export class SwipeHandle { gesture.on('panleft', onDragHorizontal); gesture.on('panright', onDragHorizontal); - let navWidth = 0; + let startX = null; + let swipeableAreaWidth = null; function onDragEnd(ev) { // TODO: POLISH THESE NUMBERS WITH GOOD MATHIFICATION - let progress = ev.gesture.center.x / navWidth; + let progress = (ev.gesture.center.x - startX) / swipeableAreaWidth; let completeSwipeBack = (progress > 0.5); let playbackRate = 4; if (completeSwipeBack) { // complete swipe back - if (progress > 0.7) { - playbackRate = 3; + if (progress > 0.9) { + playbackRate = 1; } else if (progress > 0.8) { playbackRate = 2; - } else if (progress > 0.9) { - playbackRate = 1; + } else if (progress > 0.7) { + playbackRate = 3; } } else { // cancel swipe back - if (progress < 0.3) { - playbackRate = 3; + if (progress < 0.1) { + playbackRate = 1; } else if (progress < 0.2) { playbackRate = 2; - } else if (progress < 0.1) { - playbackRate = 1; + } else if (progress < 0.3) { + playbackRate = 3; } } nav.swipeBackEnd(completeSwipeBack, progress, playbackRate); - navWidth = 0; + + startX = null; } function onDragHorizontal(ev) { - if (navWidth === 0) { - navWidth = nav.width(); + if (startX === null) { + startX = ev.gesture.center.x; + swipeableAreaWidth = nav.width() - startX; + nav.swipeBackStart(); } - nav.swipeBackProgress( ev.gesture.center.x / navWidth ); + nav.swipeBackProgress( (ev.gesture.center.x - startX) / swipeableAreaWidth ); } } diff --git a/ionic/components/nav/nav-base.js b/ionic/components/nav/nav-base.js index f17c756b7d..49e2510f23 100644 --- a/ionic/components/nav/nav-base.js +++ b/ionic/components/nav/nav-base.js @@ -20,7 +20,7 @@ export class NavBase { this.injector = injector; this.items = []; this.navCtrl = new NavController(this); - this.swipeBackTransition = null; + this.sbTransition = null; } set initial(Class) { @@ -156,7 +156,7 @@ export class NavBase { return; } - this.swipeBackResolve = null; + this.sbResolve = null; // default the direction to "back" let opts = { @@ -187,26 +187,33 @@ export class NavBase { enteringItem.state = STAGED_ENTERING_STATE; // init the transition animation - this.swipeBackTransition = Transition.create(this, opts); - this.swipeBackTransition.easing('linear'); + this.sbTransition = Transition.create(this, opts); + this.sbTransition.easing('linear'); // wait for the items to be fully staged - this.swipeBackTransition.stage().then(() => { + this.sbTransition.stage().then(() => { // update the state that the items are actively entering/leaving enteringItem.state = ACTIVELY_ENTERING_STATE; leavingItem.state = ACTIVELY_LEAVING_STATE; - let swipeBackPromise = new Promise(res => { this.swipeBackResolve = res; }); + let swipeBackPromise = new Promise(res => { this.sbResolve = res; }); - swipeBackPromise.then(() => { + swipeBackPromise.then((completeSwipeBack) => { - // transition has completed, update each item's state - enteringItem.state = ACTIVE_STATE; - leavingItem.state = CACHED_STATE; + if (completeSwipeBack) { + // swipe back has completed, update each item's state + enteringItem.state = ACTIVE_STATE; + leavingItem.state = CACHED_STATE; - // destroy any items that shouldn't stay around - this.cleanup(); + // destroy any items that shouldn't stay around + this.cleanup(); + + } else { + // cancelled the swipe back, return items to original state + leavingItem.state = ACTIVE_STATE; + enteringItem.state = CACHED_STATE; + } // allow clicks again ClickBlock(false); @@ -220,42 +227,38 @@ export class NavBase { } swipeBackEnd(completeSwipeBack, progress, playbackRate) { - console.log('swipeBackEnd, completeSwipeBack: ', completeSwipeBack, ' progress:', progress, ' playbackRate:', playbackRate); + // to reverse the animation use a negative playbackRate + if (!completeSwipeBack) playbackRate = playbackRate * -1; - this.swipeBackTransition.playbackRate(playbackRate); + this.sbTransition.playbackRate(playbackRate); - this.swipeBackTransition.play().then(() => { - this.swipeBackResolve && this.swipeBackResolve(); - - if (this.swipeBackTransition) { - this.swipeBackTransition.dispose(); - } - - this.swipeBackResolve = this.swipeBackTransition = null; + this.sbTransition.play().then(() => { + this.sbResolve && this.sbResolve(completeSwipeBack); + this.sbTransition && this.sbTransition.dispose(); + this.sbResolve = this.sbTransition = null; }); } swipeBackProgress(progress) { - if (this.swipeBackTransition) { + if (this.sbTransition) { ClickBlock(true, 4000); - this.swipeBackTransition.progress( Math.min(1, Math.max(0, progress)) ); + this.sbTransition.progress( Math.min(1, Math.max(0, progress)) ); } } - cleanup() { - for (let i = 0, ii = this.items.length; i < ii; i++) { - let item = this.items[i]; + this.items.forEach((item) => { + if (item && item.shouldDestroy) { this.remove(item); - i = 0; - ii = this.items.length; + util.dom.raf(() => { item.destroy(); }); } - } + + }); } isTransitioning() { diff --git a/ionic/transitions/ios-transition.js b/ionic/transitions/ios-transition.js index da0c5b3161..7464f88a32 100644 --- a/ionic/transitions/ios-transition.js +++ b/ionic/transitions/ios-transition.js @@ -76,7 +76,6 @@ class IOSTransition extends Animation { // leaving view moves off screen // when completed, set leavingItem to display: none leavingContent - .beforePlay.addClass(SHOW_NAV_ITEM_CSS) .afterFinish.removeClass(SHOW_NAV_ITEM_CSS) .from(TRANSFORM, CENTER) .from(OPACITY, 1);