refactor(transitions): created Transition class

Created interfaces for NavOptions, AnimationOptions and
TransitionOptions Created Transition class and move transition ts files
to their own folder.
This commit is contained in:
Adam Bradley
2016-02-10 01:57:54 -06:00
parent 7c10c4dd42
commit e6068785f6
10 changed files with 267 additions and 179 deletions

View File

@@ -1,6 +1,5 @@
import {ViewController} from '../components/nav/view-controller';
import {CSS, rafFrames, raf, transitionEnd} from '../util/dom';
import {assign} from '../util/util';
import {assign, isDefined} from '../util/util';
/**
@@ -25,12 +24,14 @@ export class Animation {
private _fOnceFns: Array<Function>;
private _wChg: boolean = false;
private _rv: boolean;
private _unregTrans: Function;
private _tmr;
public isPlaying: boolean;
public hasTween: boolean;
public meta;
constructor(ele?, opts={}) {
constructor(ele?, opts: AnimationOptions = {}) {
this._reset();
this.element(ele);
@@ -54,6 +55,8 @@ export class Animation {
this._fFns = [];
this._fOnceFns = [];
this._clearAsync();
this.isPlaying = this.hasTween = this._rv = false;
this._el = this._easing = this._dur = null;
}
@@ -106,11 +109,11 @@ export class Animation {
return this;
}
from(prop: string, val: string): Animation {
from(prop: string, val): Animation {
return this._addProp('from', prop, val);
}
to(prop: string, val: string): Animation {
to(prop: string, val): Animation {
return this._addProp('to', prop, val);
}
@@ -196,12 +199,12 @@ export class Animation {
}
}
play() {
play(opts: PlayOptions = {}) {
var self = this;
var i;
var duration = isDefined(opts.duration) ? opts.duration : self._dur;
var i, fallbackTimerId, deregTransEnd;
console.debug('Animation, play, duration', self._dur, 'easing', self._easing);
console.debug('Animation, play, duration', duration, 'easing', self._easing);
// always default that an animation does not tween
// a tween requires that an Animation class has an element
@@ -226,7 +229,10 @@ export class Animation {
// will recursively stage all child elements
self._before();
if (self._dur > 30) {
// ensure all past transition end events have been cleared
this._clearAsync();
if (duration > 30) {
// this animation has a duration, so it should animate
// place all the elements with their FROM properties
@@ -235,9 +241,9 @@ export class Animation {
self._willChange(true);
// set the TRANSITION END event
// set the async TRANSITION END event
// and run onFinishes when the transition ends
self._asyncEnd(self._dur);
self._asyncEnd(duration);
// begin each animation when everything is rendered in their place
// and the transition duration/easing is ready to go
@@ -245,7 +251,7 @@ export class Animation {
// there's been a moment and the elements are in place
// now set the TRANSITION duration/easing
self._setTrans(self._dur, false);
self._setTrans(duration, false);
// wait a few moments again to wait for the transition
// info to take hold in the DOM
@@ -264,10 +270,43 @@ export class Animation {
// just go straight to the TO properties and call it done
self._progress(1);
// so there was no animation, immediately run the after
// since there was no animation, immediately run the after
self._after();
// so there was no animation, it's done
// since there was no animation, it's done
// fire off all the onFinishes
self._onFinish();
}
}
stop(opts: PlayOptions = {}) {
var self = this;
var duration = isDefined(opts.duration) ? opts.duration : 0;
var stepValue = isDefined(opts.stepValue) ? opts.stepValue : 1;
// ensure all past transition end events have been cleared
this._clearAsync();
// set the TO properties
self._progress(stepValue);
if (duration > 30) {
// this animation has a duration, so it should animate
// place all the elements with their TO properties
// now set the TRANSITION duration
self._setTrans(duration, true);
// set the async TRANSITION END event
// and run onFinishes when the transition ends
self._asyncEnd(duration);
} else {
// this animation does not have a duration, so it should not animate
// just go straight to the TO properties and call it done
self._after();
// since there was no animation, it's done
// fire off all the onFinishes
self._onFinish();
}
@@ -275,36 +314,29 @@ export class Animation {
_asyncEnd(duration: number) {
var self = this;
var deregTransEnd, fallbackTimerId;
// set the TRANSITION END event
deregTransEnd = transitionEnd(self._transEl(), function() {
// transition has completed
console.debug('Animation, transition end');
function onTransitionEnd(ev) {
console.debug('Animation async end,', (ev ? 'transitionEnd event' : 'fallback timeout'));
// cancel the fallback timer so it doesn't fire also
clearTimeout(fallbackTimerId);
// ensure transition end events and timeouts have been cleared
self._clearAsync();
// set the after styles
self._after();
self._willChange(false);
self._onFinish();
});
}
// set the TRANSITION END event on one of the transition elements
self._unregTrans = transitionEnd(self._transEl(), onTransitionEnd);
// set a fallback timeout if the transition end event never fires
fallbackTimerId = setTimeout(function() {
// fallback timeout fired instead of the transition end
console.debug('Animation, fallback end');
self._tmr = setTimeout(onTransitionEnd, duration + 300);
}
// deregister the transition end event listener
deregTransEnd();
// set the after styles
self._after();
self._willChange(false);
self._onFinish();
}, duration + 300);
_clearAsync() {
this._unregTrans && this._unregTrans();
clearTimeout(this._tmr);
}
_progress(stepValue: number) {
@@ -565,7 +597,11 @@ export class Animation {
return this;
}
onFinish(callback: Function, onceTimeCallback: boolean = false) {
onFinish(callback: Function, onceTimeCallback: boolean = false, clearOnFinishCallacks: boolean = false) {
if (clearOnFinishCallacks) {
this._fFns = [];
this._fOnceFns = [];
}
if (onceTimeCallback) {
this._fOnceFns.push(callback);
@@ -625,7 +661,7 @@ export class Animation {
/*
STATIC CLASSES
*/
static create(name: string): Animation {
static create(name: string, opts: AnimationOptions = {}): Animation {
let AnimationClass = AnimationRegistry[name];
if (!AnimationClass) {
@@ -633,17 +669,7 @@ export class Animation {
// fallback to just the base Animation class
AnimationClass = Animation;
}
return new AnimationClass();
}
static createTransition(enteringView: ViewController, leavingView: ViewController, opts: any = {}): Animation {
let TransitionClass = AnimationRegistry[opts.animation];
if (!TransitionClass) {
// didn't find a transition animation, default to ios-transition
TransitionClass = AnimationRegistry['ios-transition'];
}
return new TransitionClass(enteringView, leavingView, opts);
return new AnimationClass(null, opts);
}
static register(name: string, AnimationClass) {
@@ -652,6 +678,16 @@ export class Animation {
}
export interface AnimationOptions {
animation?: string;
renderDelay?: number;
}
export interface PlayOptions {
duration?: number;
stepValue?: number;
}
const doc: any = document;
const TRANSFORMS = [
'translateX', 'translateY', 'translateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ',

View File

@@ -2,6 +2,7 @@ import {Component, Renderer, ElementRef} from 'angular2/core';
import {NgFor, NgIf} from 'angular2/common';
import {Animation} from '../../animations/animation';
import {Transition, TransitionOptions} from '../../transitions/transition';
import {Config} from '../../config/config';
import {Icon} from '../icon/icon';
import {isDefined} from '../../util/util';
@@ -272,9 +273,9 @@ class ActionSheetCmp {
class ActionSheetSlideIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class ActionSheetSlideIn extends Transition {
constructor(enteringView, leavingView, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -286,12 +287,12 @@ class ActionSheetSlideIn extends Animation {
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(backdrop).add(wrapper);
}
}
Animation.register('action-sheet-slide-in', ActionSheetSlideIn);
Transition.register('action-sheet-slide-in', ActionSheetSlideIn);
class ActionSheetSlideOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class ActionSheetSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -303,12 +304,12 @@ class ActionSheetSlideOut extends Animation {
this.easing('cubic-bezier(.36,.66,.04,1)').duration(300).add(backdrop).add(wrapper);
}
}
Animation.register('action-sheet-slide-out', ActionSheetSlideOut);
Transition.register('action-sheet-slide-out', ActionSheetSlideOut);
class ActionSheetMdSlideIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class ActionSheetMdSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -320,12 +321,12 @@ class ActionSheetMdSlideIn extends Animation {
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
}
}
Animation.register('action-sheet-md-slide-in', ActionSheetMdSlideIn);
Transition.register('action-sheet-md-slide-in', ActionSheetMdSlideIn);
class ActionSheetMdSlideOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class ActionSheetMdSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -337,4 +338,4 @@ class ActionSheetMdSlideOut extends Animation {
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
}
}
Animation.register('action-sheet-md-slide-out', ActionSheetMdSlideOut);
Transition.register('action-sheet-md-slide-out', ActionSheetMdSlideOut);

View File

@@ -2,6 +2,7 @@ import {Component, ElementRef, Renderer} from 'angular2/core';
import {NgClass, NgSwitch, NgIf, NgFor} from 'angular2/common';
import {Animation} from '../../animations/animation';
import {Transition, TransitionOptions} from '../../transitions/transition';
import {Config} from '../../config/config';
import {isDefined} from '../../util/util';
import {NavParams} from '../nav/nav-params';
@@ -484,9 +485,9 @@ class AlertCmp {
/**
* Animations for alerts
*/
class AlertPopIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class AlertPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -502,12 +503,12 @@ class AlertPopIn extends Animation {
.add(wrapper);
}
}
Animation.register('alert-pop-in', AlertPopIn);
Transition.register('alert-pop-in', AlertPopIn);
class AlertPopOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class AlertPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -523,12 +524,12 @@ class AlertPopOut extends Animation {
.add(wrapper);
}
}
Animation.register('alert-pop-out', AlertPopOut);
Transition.register('alert-pop-out', AlertPopOut);
class AlertMdPopIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class AlertMdPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -544,12 +545,12 @@ class AlertMdPopIn extends Animation {
.add(wrapper);
}
}
Animation.register('alert-md-pop-in', AlertMdPopIn);
Transition.register('alert-md-pop-in', AlertMdPopIn);
class AlertMdPopOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(null, opts);
class AlertMdPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('.backdrop'));
@@ -565,6 +566,6 @@ class AlertMdPopOut extends Animation {
.add(wrapper);
}
}
Animation.register('alert-md-pop-out', AlertMdPopOut);
Transition.register('alert-md-pop-out', AlertMdPopOut);
let alertIds = -1;

View File

@@ -1,5 +1,6 @@
import {ViewController} from '../nav/view-controller';
import {Animation} from '../../animations/animation';
import {Transition, TransitionOptions} from '../../transitions/transition';
/**
* @name Modal
@@ -129,10 +130,11 @@ export class Modal extends ViewController {
/**
* Animations for modals
*/
class ModalSlideIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(enteringView.pageRef(), opts);
class ModalSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
this
.element(enteringView.pageRef())
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(400)
.fromTo('translateY', '100%', '0%')
@@ -146,25 +148,27 @@ class ModalSlideIn extends Animation {
}
}
}
Animation.register('modal-slide-in', ModalSlideIn);
Transition.register('modal-slide-in', ModalSlideIn);
class ModalSlideOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(leavingView.pageRef(), opts);
class ModalSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
this
.element(leavingView.pageRef())
.easing('ease-out')
.duration(250)
.fromTo('translateY', '0%', '100%');
}
}
Animation.register('modal-slide-out', ModalSlideOut);
Transition.register('modal-slide-out', ModalSlideOut);
class ModalMDSlideIn extends Animation {
constructor(enteringView, leavingView, opts) {
super(enteringView.pageRef(), opts);
class ModalMDSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
this
.element(enteringView.pageRef())
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(280)
.fromTo('translateY', '40px', '0px')
@@ -179,17 +183,18 @@ class ModalMDSlideIn extends Animation {
}
}
}
Animation.register('modal-md-slide-in', ModalMDSlideIn);
Transition.register('modal-md-slide-in', ModalMDSlideIn);
class ModalMDSlideOut extends Animation {
constructor(enteringView, leavingView, opts) {
super(leavingView.pageRef(), opts);
class ModalMDSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
this
.element(leavingView.pageRef())
.duration(200)
.easing('cubic-bezier(0.47,0,0.745,0.715)')
.fromTo('translateY', '0px', '40px')
.fadeOut();
}
}
Animation.register('modal-md-slide-out', ModalMDSlideOut);
Transition.register('modal-md-slide-out', ModalMDSlideOut);

View File

@@ -1,16 +1,16 @@
import {Compiler, ElementRef, Injector, provide, NgZone, AppViewManager, Renderer, ResolvedProvider, Type} from 'angular2/core';
import {wtfLeave, wtfCreateScope, WtfScopeFn, wtfStartTimeRange, wtfEndTimeRange} from 'angular2/instrumentation';
import {Animation} from '../../animations/animation';
import {Config} from '../../config/config';
import {Ion} from '../ion';
import {IonicApp} from '../app/app';
import {isBoolean, array, pascalCaseToDashCase} from '../../util/util';
import {Keyboard} from '../../util/keyboard';
import {NavParams} from './nav-params';
import {NavRouter} from './nav-router';
import {raf, rafFrames} from '../../util/dom';
import {pascalCaseToDashCase} from '../../util/util';
import {raf} from '../../util/dom';
import {SwipeBackGesture} from './swipe-back';
import {Transition} from '../../transitions/transition';
import {ViewController} from './view-controller';
/**
@@ -106,11 +106,11 @@ import {ViewController} from './view-controller';
export class NavController extends Ion {
private _transIds = 0;
private _init = false;
private _lastTrans;
private _lastTrans: Transition;
protected _ids: number = -1;
protected _sbEnabled: any;
protected _sbThreshold: any;
protected _sbTrans: any = null;
protected _sbTrans: Transition = null;
protected _trnsDelay: any;
protected _trnsTime: number = 0;
protected _views: Array<ViewController> = [];
@@ -182,7 +182,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise when done
*/
setRoot(page: Type, params: any = {}, opts: any = {}): Promise<any> {
setRoot(page: Type, params: any = {}, opts: NavOptions = {}): Promise<any> {
return this.setPages([{page, params}], opts);
}
@@ -259,7 +259,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass
* @returns {Promise} Returns a promise when the pages are set
*/
setPages(pages: Array<{page: Type, params?: any}>, opts: any = {}): Promise<any> {
setPages(pages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise<any> {
if (!pages || !pages.length) {
return Promise.resolve();
}
@@ -307,7 +307,7 @@ export class NavController extends Ion {
/**
* @private
*/
private setViews(components, opts = {}) {
private setViews(components, opts: NavOptions = {}) {
console.warn('setViews() deprecated, use setPages() instead');
return this.setPages(components, opts);
}
@@ -377,14 +377,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise, which resolves when the transition has completed
*/
push(page: Type,
params: any={},
opts: {
animate?: boolean,
animation?: string
direction?: string
}={}
) {
push(page: Type, params: any = {}, opts: NavOptions = {}) {
return this.insertPages(-1, [{page: page, params: params}], opts);
}
@@ -413,7 +406,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise, which resolves when the transition has completed
*/
present(enteringView: ViewController, opts: any = {}): Promise<any> {
present(enteringView: ViewController, opts: NavOptions = {}): Promise<any> {
let rootNav = this.rootNav;
if (rootNav['_tabs']) {
@@ -424,7 +417,6 @@ export class NavController extends Ion {
}
opts.keyboardClose = false;
opts.skipCache = true;
opts.direction = 'forward';
if (!opts.animation) {
@@ -433,7 +425,6 @@ export class NavController extends Ion {
enteringView.setLeavingOpts({
keyboardClose: false,
skipCache: true,
direction: 'back',
animation: enteringView.getTransitionName('back')
});
@@ -465,7 +456,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise when the page has been inserted into the navigation stack
*/
insert(insertIndex: number, page: Type, params: any = {}, opts: any = {}): Promise<any> {
insert(insertIndex: number, page: Type, params: any = {}, opts: NavOptions = {}): Promise<any> {
return this.insertPages(insertIndex, [{page: page, params: params}], opts);
}
@@ -497,12 +488,12 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise when the pages have been inserted into the navigation stack
*/
insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts: any = {}): Promise<any> {
insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise<any> {
let views = insertPages.map(p => new ViewController(p.page, p.params));
return this._insertViews(insertIndex, views, opts);
}
private _insertViews(insertIndex: number, insertViews: Array<ViewController>, opts: any = {}): Promise<any> {
private _insertViews(insertIndex: number, insertViews: Array<ViewController>, opts: NavOptions = {}): Promise<any> {
if (!insertViews || !insertViews.length) {
return Promise.reject('invalid pages');
}
@@ -526,7 +517,7 @@ export class NavController extends Ion {
// transition in, but was simply inserted somewhere in the stack
// go backwards through the stack and find the first active view
// which could be active or one ready to enter
for (let i = this._views.length - 1; i >= 0; i--) {
for (var i = this._views.length - 1; i >= 0; i--) {
if (this._views[i].state === STATE_ACTIVE || this._views[i].state === STATE_INIT_ENTER) {
// found the view at the end of the stack that's either
// already active or it is about to enter
@@ -627,7 +618,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise when the transition is completed
*/
pop(opts: any = {}): Promise<any> {
pop(opts: NavOptions = {}): Promise<any> {
// get the index of the active view
// which will become the view to be leaving
let activeView = this.getByState(STATE_TRANS_ENTER) ||
@@ -640,7 +631,7 @@ export class NavController extends Ion {
* Similar to `pop()`, this method let's you navigate back to the root of the stack, no matter how many views that is
* @param {object} [opts={}] Any options you want to use pass to transtion
*/
popToRoot(opts = {}): Promise<any> {
popToRoot(opts: NavOptions = {}): Promise<any> {
return this.popTo(this.first(), opts);
}
@@ -649,7 +640,7 @@ export class NavController extends Ion {
* @param {ViewController} view to pop to
* @param {object} [opts={}] Any options you want to use pass to transtion
*/
popTo(view: ViewController, opts: any = {}): Promise<any> {
popTo(view: ViewController, opts: NavOptions = {}): Promise<any> {
let startIndex = this.indexOf(view);
let activeView = this.getByState(STATE_TRANS_ENTER) ||
this.getByState(STATE_INIT_ENTER) ||
@@ -678,7 +669,7 @@ export class NavController extends Ion {
* @param {object} [opts={}] Any options you want to use pass to transtion.
* @returns {Promise} Returns a promise when the page has been removed.
*/
remove(startIndex: number = -1, removeCount: number = 1, opts: any = {}): Promise<any> {
remove(startIndex: number = -1, removeCount: number = 1, opts: NavOptions = {}): Promise<any> {
if (startIndex === -1) {
startIndex = this._views.length - 1;
@@ -705,13 +696,16 @@ export class NavController extends Ion {
}
if (this._lastTrans) {
this._lastTrans.playbackRate(100).onFinish(() => {
opts.animate = false;
this._transition(forcedActive, null, opts, () => {
// transition has completed!!
resolve();
});
});
this._lastTrans
.onFinish(() => {
opts.animate = false;
this._transition(forcedActive, null, opts, () => {
// transition has completed!!
resolve();
});
}, false, true)
.stop();
this._lastTrans.destroy();
this._lastTrans = null;
} else {
@@ -761,7 +755,7 @@ export class NavController extends Ion {
let view: ViewController = null;
// loop through each view that is set to be removed
for (let i = startIndex, ii = removeCount + startIndex; i < ii; i++) {
for (var i = startIndex, ii = removeCount + startIndex; i < ii; i++) {
view = this.getByIndex(i);
if (!view) break;
@@ -792,7 +786,7 @@ export class NavController extends Ion {
// from the index of the leaving view, go backwards and
// find the first view that is inactive
for (let i = this.indexOf(view) - 1; i >= 0; i--) {
for (var i = this.indexOf(view) - 1; i >= 0; i--) {
if (this._views[i].state === STATE_INACTIVE) {
this._views[i].state = STATE_INIT_ENTER;
break;
@@ -813,7 +807,7 @@ export class NavController extends Ion {
// from the index of the leaving view, go backwards and
// find the first view that is inactive so it can be the entering
for (let i = this.indexOf(view) - 1; i >= 0; i--) {
for (var i = this.indexOf(view) - 1; i >= 0; i--) {
if (this._views[i].state === STATE_INACTIVE) {
this._views[i].state = STATE_INIT_ENTER;
break;
@@ -855,7 +849,7 @@ export class NavController extends Ion {
/**
* @private
*/
private _transition(enteringView: ViewController, leavingView: ViewController, opts, done: Function) {
private _transition(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, done: Function) {
let transId = ++this._transIds;
if (enteringView === leavingView) {
@@ -902,7 +896,7 @@ export class NavController extends Ion {
/**
* @private
*/
private _render(transId, enteringView: ViewController, leavingView: ViewController, opts: any, done: Function) {
private _render(transId, enteringView: ViewController, leavingView: ViewController, opts: NavOptions, done: Function) {
// compile/load the view into the DOM
if (enteringView.state === STATE_INACTIVE) {
@@ -948,7 +942,7 @@ export class NavController extends Ion {
/**
* @private
*/
private _postRender(transId, enteringView: ViewController, leavingView: ViewController, isAlreadyTransitioning: boolean, opts: any, done: Function) {
private _postRender(transId, enteringView: ViewController, leavingView: ViewController, isAlreadyTransitioning: boolean, opts: NavOptions, done: Function) {
// called after _render has completed and the view is compiled/loaded
if (enteringView.state === STATE_INACTIVE) {
@@ -1007,7 +1001,7 @@ export class NavController extends Ion {
/**
* @private
*/
private _beforeTrans(enteringView: ViewController, leavingView: ViewController, opts: any, done: Function) {
private _beforeTrans(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, done: Function) {
// called after one raf from postRender()
// create the transitions animation, play the animation
// when the transition ends call wait for it to end
@@ -1025,15 +1019,20 @@ export class NavController extends Ion {
this._zone.runOutsideAngular(() => {
// init the transition animation
opts.renderDelay = opts.transitionDelay || this._trnsDelay;
let transitionOpts = {
animation: opts.animation,
direction: opts.direction,
duration: opts.duration,
easing: opts.easing,
renderDelay: opts.transitionDelay || this._trnsDelay,
isRTL: this.config.platform.isRTL()
};
// set if this app is right-to-left or not
opts.isRTL = this.config.platform.isRTL();
let transAnimation = Animation.createTransition(enteringView,
leavingView,
opts);
let transAnimation = Transition.createTransition(enteringView,
leavingView,
transitionOpts);
this._lastTrans && this._lastTrans.destroy();
this._lastTrans = transAnimation;
if (opts.animate === false) {
@@ -1070,7 +1069,7 @@ export class NavController extends Ion {
/**
* @private
*/
private _afterTrans(enteringView: ViewController, leavingView: ViewController, opts: any, done: Function) {
private _afterTrans(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, done: Function) {
// transition has completed, update each view's state
// place back into the zone, run didEnter/didLeave
// call the final callback when done
@@ -1176,7 +1175,7 @@ export class NavController extends Ion {
let activeViewIndex = this.indexOf(this.getActive());
let destroys = this._views.filter(v => v.state === STATE_REMOVE_AFTER_TRANS);
for (let i = activeViewIndex + 1; i < this._views.length; i++) {
for (var i = activeViewIndex + 1; i < this._views.length; i++) {
if (this._views[i].state === STATE_INACTIVE) {
destroys.push(this._views[i]);
}
@@ -1193,7 +1192,7 @@ export class NavController extends Ion {
/**
* @private
*/
loadPage(view: ViewController, navbarContainerRef, opts: any, done: Function) {
loadPage(view: ViewController, navbarContainerRef, opts: NavOptions, done: Function) {
let wtfTimeRangeScope = wtfStartTimeRange('NavController#loadPage', view.name);
// guts of DynamicComponentLoader#loadIntoLocation
@@ -1295,19 +1294,8 @@ export class NavController extends Ion {
// wait for the new view to complete setup
this._render(0, enteringView, leavingView, {}, () => {
this._zone.runOutsideAngular(() => {
// set that the new view pushed on the stack is staged to be entering/leaving
// staged state is important for the transition to find the correct view
// enteringView.state = STATE_RENDERED_ENTER;
// leavingView.state = STATE_RENDERED_LEAVE;
// init the swipe back transition animation
this._sbTrans = Animation.createTransition(enteringView, leavingView, opts);
this._sbTrans.easing('linear').progressStart();
});
});
}
/**
@@ -1321,7 +1309,7 @@ export class NavController extends Ion {
this.setTransitioning(true, 4000);
// set the transition animation's progress
this._sbTrans.progress(value);
this._sbTrans.progressStep(value);
}
}
@@ -1336,8 +1324,7 @@ export class NavController extends Ion {
this._app.setEnabled(false);
this.setTransitioning(true);
this._sbTrans.progressEnd(completeSwipeBack, rate).then(() => {
this._sbTrans.onFinish(() => {
this._zone.run(() => {
// find the views that were entering and leaving
let enteringView = null;// this._getStagedEntering();
@@ -1376,14 +1363,15 @@ export class NavController extends Ion {
}
// empty out and dispose the swipe back transition animation
this._sbTrans && this._sbTrans.dispose();
this._sbTrans && this._sbTrans.destroy();
this._sbTrans = null;
// all done!
//this._transComplete();
});
});
}, true);
this._sbTrans.progressEnd(completeSwipeBack, 0.5);
}
/**
@@ -1475,7 +1463,7 @@ export class NavController extends Ion {
* @returns {ViewController}
*/
getByState(state: string): ViewController {
for (let i = this._views.length - 1; i >= 0; i--) {
for (var i = this._views.length - 1; i >= 0; i--) {
if (this._views[i].state === state) {
return this._views[i];
}
@@ -1595,6 +1583,18 @@ export class NavController extends Ion {
}
export interface NavOptions {
animate?: boolean;
animation?: string;
direction?: string;
duration?: number;
easing?: string;
keyboardClose?: boolean;
preload?: boolean;
transitionDelay?: number;
postLoad?: Function
}
const STATE_ACTIVE = 'active';
const STATE_INACTIVE = 'inactive';
const STATE_INIT_ENTER = 'init_enter';

View File

@@ -1,7 +1,7 @@
import {Output, EventEmitter, Type, TemplateRef, ViewContainerRef, ElementRef, Renderer} from 'angular2/core';
import {Navbar} from '../navbar/navbar';
import {NavController} from './nav-controller';
import {NavController, NavOptions} from './nav-controller';
import {NavParams} from './nav-params';
@@ -112,7 +112,7 @@ export class ViewController {
/**
* @private
*/
setLeavingOpts(opts) {
setLeavingOpts(opts: NavOptions) {
this._leavingOpts = opts;
}
@@ -183,7 +183,7 @@ export class ViewController {
* @private
*/
destroy() {
for (let i = 0; i < this._destroys.length; i++) {
for (var i = 0; i < this._destroys.length; i++) {
this._destroys[i]();
}
this._destroys = [];

View File

@@ -24,5 +24,5 @@ export * from './translation/translate_pipe'
import './config/modes'
import './platform/registry'
import './animations/builtins'
import './animations/ios-transition'
import './animations/md-transition'
import './transitions/transition-ios'
import './transitions/transition-md'

View File

@@ -1,4 +1,6 @@
import {Animation} from './animation';
import {Animation} from '../animations/animation';
import {Transition, TransitionOptions} from './transition';
import {ViewController} from '../components/nav/view-controller';
const DURATION = 500;
const EASING = 'cubic-bezier(0.36,0.66,0.04,1)';
@@ -11,10 +13,10 @@ const OFF_OPACITY = 0.8;
const SHOW_BACK_BTN_CSS = 'show-back-button';
class IOSTransition extends Animation {
class IOSTransition extends Transition {
constructor(enteringView, leavingView, opts) {
super(null, opts);
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
this.duration(opts.duration || DURATION);
this.easing(opts.easing || EASING);
@@ -187,4 +189,4 @@ class IOSTransition extends Animation {
}
Animation.register('ios-transition', IOSTransition);
Transition.register('ios-transition', IOSTransition);

View File

@@ -1,4 +1,6 @@
import {Animation} from './animation';
import {Animation} from '../animations/animation';
import {Transition, TransitionOptions} from './transition';
import {ViewController} from '../components/nav/view-controller';
const TRANSLATEY = 'translateY';
const OFF_BOTTOM = '40px';
@@ -6,10 +8,10 @@ const CENTER = '0px'
const SHOW_BACK_BTN_CSS = 'show-back-button';
class MDTransition extends Animation {
class MDTransition extends Transition {
constructor(enteringView, leavingView, opts) {
super(null, opts);
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
// what direction is the transition going
let backDirection = (opts.direction === 'back');
@@ -60,4 +62,4 @@ class MDTransition extends Animation {
}
Animation.register('md-transition', MDTransition);
Transition.register('md-transition', MDTransition);

View File

@@ -0,0 +1,41 @@
import {Animation} from '../animations/animation';
import {ViewController} from '../components/nav/view-controller';
/**
* @private
**/
export class Transition extends Animation {
constructor(opts: TransitionOptions) {
super(null, {
renderDelay: opts.renderDelay
});
}
static createTransition(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions): Transition {
let TransitionClass = TransitionRegistry[opts.animation];
if (!TransitionClass) {
// didn't find a transition animation, default to ios-transition
TransitionClass = TransitionRegistry['ios-transition'];
}
return new TransitionClass(enteringView, leavingView, opts);
}
static register(name: string, TransitionClass) {
TransitionRegistry[name] = TransitionClass;
}
}
export interface TransitionOptions {
animation: string;
duration: number;
easing: string;
direction: string;
renderDelay?: number;
isRTL?: boolean;
}
let TransitionRegistry = {};