update animations

This commit is contained in:
Adam Bradley
2015-10-10 23:52:01 -05:00
parent 02cccbf47e
commit 6c44ae6246
13 changed files with 302 additions and 238 deletions

View File

@@ -110,6 +110,13 @@ export class Animation {
return this._duration || (this._parent && this._parent.duration()) || 0;
}
clearDuration() {
this._duration = null;
for (let i = 0, l = this._chld.length; i < l; i++) {
this._chld[i].clearDuration();
}
}
easing(name, opts) {
if (arguments.length) {
this._easing = {
@@ -184,6 +191,7 @@ export class Animation {
},
setStyles: (styles) => {
this._bfSty = styles;
return this;
}
}
}

View File

@@ -113,6 +113,10 @@ ion-view.pane-view {
flex-direction: column;
}
ion-view.pane-view {
background: transparent;
}
ion-view {
display: none;
position: absolute;

View File

@@ -5,13 +5,10 @@
ion-navbar.toolbar {
position: absolute;
}
ion-navbar {
transform: translate3d(100%, 0px, 0px);
display: none;
&.show-navbar {
transform: translate3d(0px, 0px, 0px);
display: flex;
}
}

View File

@@ -79,7 +79,7 @@ export class Navbar extends ToolbarBase {
renderer.setElementClass(elementRef, 'toolbar', true);
this.app = app;
viewCtrl && viewCtrl.navbarView(this);
viewCtrl && viewCtrl.setNavbar(this);
this.bbIcon = config.get('backButtonIcon');
this.bbDefault = config.get('backButtonText');

View File

@@ -476,6 +476,7 @@ export class NavController extends Ion {
let transAnimation = Transition.create(this, opts);
if (opts.animate === false) {
// force it to not animate the elements, just apply the "to" styles
transAnimation.clearDuration();
transAnimation.duration(0);
}

View File

@@ -230,7 +230,7 @@ export class Nav extends NavController {
viewCtrl.setInstance(componentRef.instance);
// remember the ElementRef to the content that was just created
viewCtrl.viewElementRef(componentRef.location);
viewCtrl.setContentRef(componentRef.location);
// get the NavController's container for navbars, which is
// the place this NavController will add each ViewController's navbar

View File

@@ -13,8 +13,6 @@ export class ViewController {
this.instance = null;
this.state = 0;
this.disposals = [];
this.navbarTemplateRef = null;
}
setContent(content) {
@@ -104,37 +102,42 @@ export class ViewController {
* @private
*/
setNavbarTemplateRef(templateRef) {
this.navbarTemplateRef = templateRef;
this._nbTmpRef = templateRef;
}
/**
* @private
*/
getNavbarTemplateRef() {
return this.navbarTemplateRef;
}
/**
* TODO
* @param {TODO} val TODO
* @returns {TODO} TODO
*/
viewElementRef(val) {
if (arguments.length) {
this._vwEle = val;
}
return this._vwEle;
return this._nbTmpRef;
}
/**
* TODO
* @returns {TODO} TODO
*/
navbarView() {
if (arguments.length) {
this._nbView = arguments[0];
}
return this._nbView;
setContentRef(contentElementRef) {
this._cntRef = contentElementRef;
}
/**
* TODO
* @returns {TODO} TODO
*/
contentRef() {
return this._cntRef;
}
setNavbar(navbarView) {
this._nbVw = navbarView;
}
/**
* TODO
* @returns {TODO} TODO
*/
getNavbar() {
return this._nbVw;
}
/**
@@ -142,10 +145,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
navbarRef() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getElementRef();
}
let navbar = this.getNavbar();
return navbar && navbar.getElementRef();
}
/**
@@ -153,10 +154,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
titleRef() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getTitleRef();
}
let navbar = this.getNavbar();
return navbar && navbar.getTitleRef();
}
/**
@@ -164,10 +163,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
navbarItemRefs() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getItemRefs();
}
let navbar = this.getNavbar();
return navbar && navbar.getItemRefs();
}
/**
@@ -175,10 +172,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
backBtnRef() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getBackButtonRef();
}
let navbar = this.getNavbar();
return navbar && navbar.getBackButtonRef();
}
/**
@@ -186,10 +181,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
backBtnTextRef() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getBackButtonTextRef();
}
let navbar = this.getNavbar();
return navbar && navbar.getBackButtonTextRef();
}
/**
@@ -197,10 +190,8 @@ export class ViewController {
* @returns {TODO} TODO
*/
navbarBgRef() {
let navbarView = this.navbarView();
if (navbarView) {
return navbarView.getNativeElement().querySelector('.toolbar-background');
}
let navbar = this.getNavbar();
return navbar && navbar.getNativeElement().querySelector('.toolbar-background');
}
@@ -231,10 +222,8 @@ export class ViewController {
* will fire, whether it was the first load or loaded from the cache.
*/
didEnter() {
let navbarView = this.navbarView();
if (navbarView) {
navbarView.didEnter();
}
let navbar = this.getNavbar();
navbar && navbar.didEnter();
this.instance && this.instance.onPageDidEnter && this.instance.onPageDidEnter();
}

View File

@@ -92,14 +92,14 @@ export class Tab extends NavController {
super(tabs, app, config, elementRef, compiler, loader, viewManager, zone);
this.tabs = tabs;
let viewCtrl = this.viewCtrl = new ViewController(tabs.Host);
let viewCtrl = this.viewCtrl = new ViewController(tabs);
viewCtrl.setInstance(this);
viewCtrl.viewElementRef(elementRef);
viewCtrl.setContentRef(elementRef);
this._initTab = tabs.addTab(this);
this.navbarView = viewCtrl.navbarView = () => {
this.getNavbar = viewCtrl.getNavbar = () => {
let activeView = this.getActive();
return activeView && activeView.navbarView();
return activeView && activeView.getNavbar();
};
viewCtrl.enableBack = () => {
@@ -164,7 +164,7 @@ export class Tab extends NavController {
viewCtrl.setInstance(componentRef.instance);
// remember the ElementRef to the content that was just created
viewCtrl.viewElementRef(componentRef.location);
viewCtrl.setContentRef(componentRef.location);
// get the NavController's container for navbars, which is
// the place this NavController will add each ViewController's navbar

View File

@@ -118,10 +118,17 @@ export class Tabs extends NavController {
// special overrides for the Tabs ViewController
// the Tabs ViewController does not have it's own navbar
// so find the navbar it should use within it's active Tab
viewCtrl.navbarView = () => {
viewCtrl.getNavbar = () => {
let activeTab = this.getActive();
if (activeTab && activeTab.instance) {
return activeTab.instance.navbarView();
return activeTab.instance.getNavbar();
}
};
viewCtrl.contentRef = () => {
let activeTab = this.getActive();
if (activeTab && activeTab.instance) {
return activeTab.instance.viewCtrl.contentRef();
}
};

View File

@@ -64,7 +64,7 @@ class Tab1Page1 {
@Page({
template: '' +
'<ion-navbar *navbar>' +
'<ion-navbar *navbar primary>' +
'<ion-title>Tabs 1 Page 2</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +

View File

@@ -1,7 +1,6 @@
import {Transition} from './transition';
import {Transition, ViewTransition} from './transition';
import {Animation} from '../animations/animation';
const DURATION = 550;
const EASING = 'cubic-bezier(0.36,0.66,0.04,1)';
@@ -15,97 +14,74 @@ const OFF_OPACITY = 0.8;
class IOSTransition extends Transition {
constructor(nav, opts) {
super(nav, opts);
constructor(navCtrl, opts) {
super(navCtrl, opts, IOSEnteringTransition, IOSLeavingTransition);
// global duration and easing for all child animations
this.duration(DURATION);
this.easing(EASING);
}
// entering item moves to center
this.enteringContent
}
class IOSEnteringTransition extends ViewTransition {
constructor(navCtrl, viewCtrl, opts) {
super(navCtrl, viewCtrl, opts);
this.content
.to(TRANSLATEX, CENTER)
.to(OPACITY, 1)
.before.setStyles({ zIndex: this.enteringZ });
.before.setStyles({ zIndex: viewCtrl.index });
this.enteringTitle
this.navbar.before.addClass('show-navbar');
this.title
.fadeIn()
.to(TRANSLATEX, CENTER);
this.enteringNavbarBg
this.navbarBg
.to(TRANSLATEX, CENTER);
// leaving view moves off screen
this.leavingContent
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1)
.before.setStyles({ zIndex: this.leavingZ });
this.navbarItems
.fadeIn();
this.leavingTitle
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1);
this.leavingNavbarBg
.from(TRANSLATEX, CENTER);
if (viewCtrl.enableBack()) {
this.backButton
.before.addClass('show-back-button')
.fadeIn();
}
// set properties depending on direction
if (opts.direction === 'back') {
// back direction
this.enteringContent
this.content
.from(TRANSLATEX, OFF_LEFT)
.from(OPACITY, OFF_OPACITY)
.to(OPACITY, 1);
this.enteringTitle
this.title
.from(TRANSLATEX, OFF_LEFT);
this.enteringNavbarBg
this.navbarBg
.from(TRANSLATEX, OFF_LEFT);
this.leavingContent
.to(TRANSLATEX, '100%')
.to(OPACITY, 1);
this.leavingTitle
.to(TRANSLATEX, '100%')
.to(OPACITY, 0);
this.leavingNavbarBg
.to(TRANSLATEX, '100%');
if (this.leaving && this.leaving.enableBack() && this.viewWidth() > 200) {
let leavingBackButtonText = new Animation(this.leaving.backBtnTextRef());
leavingBackButtonText.fromTo(TRANSLATEX, CENTER, (this.viewWidth() / 2) + 'px');
this.leavingNavbar.add(leavingBackButtonText);
}
} else {
// forward direction
this.enteringContent
this.content
.from(TRANSLATEX, '99.5%')
.from(OPACITY, 1);
this.enteringTitle
this.title
.from(TRANSLATEX, '99.5%');
this.enteringNavbarBg
.from(TRANSLATEX, '99.5%');
this.navbarBg
.from(TRANSLATEX, '99.5%')
.fadeIn();
this.leavingContent
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, OFF_OPACITY);
this.leavingTitle
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, 0);
this.leavingNavbarBg
.to(TRANSLATEX, OFF_LEFT);
if (this.entering.enableBack() && this.viewWidth() > 200) {
let enteringBackButtonText = new Animation(this.entering.backBtnTextRef());
enteringBackButtonText.fromTo(TRANSLATEX, (this.viewWidth() / 2) + 'px', CENTER);
this.enteringNavbar.add(enteringBackButtonText);
if (viewCtrl.enableBack()) {
let backBtnText = new Animation(viewCtrl.backBtnTextRef());
backBtnText.fromTo(TRANSLATEX, (300) + 'px', CENTER);
this.navbar.add(backBtnText);
}
}
@@ -113,4 +89,72 @@ class IOSTransition extends Transition {
}
class IOSLeavingTransition extends ViewTransition {
constructor(navCtrl, viewCtrl, opts) {
super(navCtrl, viewCtrl, opts);
// leaving viewCtrl moves off screen
this.content
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1)
.before.setStyles({ zIndex: viewCtrl.index })
.after.removeClass('show-view');
this.title
.from(TRANSLATEX, CENTER)
.from(OPACITY, 1);
this.navbarBg
.from(TRANSLATEX, CENTER);
this.navbarItems
.fadeOut();
this.backButton
.after.removeClass('show-back-button')
.fadeOut();
this.navbar.after.removeClass('show-navbar');
// set properties depending on direction
if (opts.direction === 'back') {
// back direction
this.content
.to(TRANSLATEX, '100%')
.to(OPACITY, 1);
this.title
.to(TRANSLATEX, '100%')
.to(OPACITY, 0);
this.navbarBg
.to(TRANSLATEX, '100%')
.fadeOut();
// if (this.leaving && this.leaving.enableBack() && this.viewWidth() > 200) {
// let leavingBackButtonText = new Animation(this.leaving.backBtnTextRef());
// leavingBackButtonText.fromTo(TRANSLATEX, CENTER, (this.viewWidth() / 2) + 'px');
// this.leavingNavbar.add(leavingBackButtonText);
// }
} else {
// forward direction
this.content
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, OFF_OPACITY);
this.title
.to(TRANSLATEX, OFF_LEFT)
.to(OPACITY, 0);
this.navbarBg
.to(TRANSLATEX, OFF_LEFT);
}
}
}
Transition.register('ios', IOSTransition);

View File

@@ -1,70 +1,68 @@
import {Transition} from './transition';
import {Transition, ViewTransition} from './transition';
import {Animation} from '../animations/animation';
const TRANSLATEY = 'translateY';
const TRANSLATE_Y = 'translateY';
const OFF_BOTTOM = '40px';
const CENTER = '0px'
class MaterialTransition extends Transition {
class MDTransition extends Transition {
constructor(nav, opts) {
constructor(navCtrl, opts) {
opts.renderDelay = 160;
super(nav, opts);
super(navCtrl, opts, MDEnteringTransition, MDLeavingTransition);
}
}
class MDEnteringTransition extends ViewTransition {
constructor(navCtrl, viewCtrl, opts) {
super(navCtrl, viewCtrl, opts);
// entering item moves in bottom to center
this.enteringContent
.to(TRANSLATEY, CENTER)
.before.setStyles({ zIndex: this.enteringZ });
this.content
.to(TRANSLATE_Y, CENTER)
.before.setStyles({ zIndex: viewCtrl.index });
// entering item moves in bottom to center
this.enteringNavbar
.to(TRANSLATEY, CENTER)
.before.setStyles({ zIndex: this.enteringZ + 10 });
this.navbar
.to(TRANSLATE_Y, CENTER)
.fadeIn()
.before.addClass('show-navbar')
.before.setStyles({ zIndex: viewCtrl.index + 10 });
// leaving view stays put
this.leavingContent
.before.setStyles({ zIndex: this.leavingZ });
this.leavingNavbar
.before.setStyles({ zIndex: this.leavingZ + 10 });
if (viewCtrl.enableBack()) {
this.backButton.before.addClass('show-back-button');
}
// set properties depending on direction
if (opts.direction === 'back') {
this.duration(200).easing('cubic-bezier(0.47,0,0.745,0.715)');
// back direction
this.enteringContent
.from(TRANSLATEY, CENTER);
this.content
.from(TRANSLATE_Y, CENTER);
this.enteringNavbar
.from(TRANSLATEY, CENTER);
// leaving view goes center to bottom
this.leavingContent
.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM)
.fadeOut();
this.leavingNavbar
.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM)
.fadeOut();
this.navbar
.from(TRANSLATE_Y, CENTER);
} else {
// forward direction
this.duration(280).easing('cubic-bezier(0.36,0.66,0.04,1)');
this.enteringContent
.from(TRANSLATEY, OFF_BOTTOM)
this.content
.from(TRANSLATE_Y, OFF_BOTTOM)
.fadeIn();
this.enteringNavbar
.from(TRANSLATEY, OFF_BOTTOM)
this.navbar
.from(TRANSLATE_Y, OFF_BOTTOM)
.fadeIn();
}
let viewLength = nav.length();
if (nav.tabs && (viewLength === 1 || viewLength === 2)) {
let tabBarEle = nav.tabs.elementRef.nativeElement.querySelector('ion-tab-bar-section');
let viewLength = navCtrl.length();
if ((viewLength === 1 || viewLength === 2) && navCtrl.tabs) {
let tabBarEle = navCtrl.tabs.elementRef.nativeElement.querySelector('ion-tab-bar-section');
let tabBar = new Animation(tabBarEle);
if (viewLength === 1 && opts.direction == 'back') {
@@ -83,4 +81,54 @@ class MaterialTransition extends Transition {
}
Transition.register('md', MaterialTransition);
class MDLeavingTransition extends ViewTransition {
constructor(navCtrl, viewCtrl, opts) {
super(navCtrl, viewCtrl, opts);
// leaving viewCtrl stays put
this.content
.before.setStyles({ zIndex: viewCtrl.index })
.after.removeClass('show-view');
this.navbar
.before.setStyles({ zIndex: viewCtrl.index + 10 })
.after.removeClass('show-navbar')
.fadeOut();
// set properties depending on direction
if (opts.direction === 'back') {
this.duration(200).easing('cubic-bezier(0.47,0,0.745,0.715)');
// leaving viewCtrl goes center to bottom
this.content
.fromTo(TRANSLATE_Y, CENTER, OFF_BOTTOM)
.fadeOut();
this.navbar
.fromTo(TRANSLATE_Y, CENTER, OFF_BOTTOM)
.fadeOut();
}
let viewLength = navCtrl.length();
if ((viewLength === 1 || viewLength === 2) && navCtrl.tabs) {
let tabBarEle = navCtrl.tabs.elementRef.nativeElement.querySelector('ion-tab-bar-section');
let tabBar = new Animation(tabBarEle);
if (viewLength === 1 && opts.direction == 'back') {
tabBar.fromTo('height', '0px', '69px');
tabBar.fadeIn();
} else if (viewLength === 2 && opts.direction == 'forward') {
tabBar.fromTo('height', '69px', '0px');
tabBar.fadeOut();
}
this.add(tabBar);
}
}
}
Transition.register('md', MDTransition);

View File

@@ -5,103 +5,69 @@ const SHOW_NAVBAR_CSS = 'show-navbar';
const SHOW_VIEW_CSS = 'show-view';
const SHOW_BACK_BUTTON = 'show-back-button';
let TransitionRegistry = {};
export class Transition extends Animation {
constructor(nav, opts) {
constructor(navCtrl, opts, EnteringTransition, LeavingTransition) {
super(null, opts);
// get the entering and leaving items
let entering = this.entering = nav.getStagedEnteringView();
let leaving = this.leaving = nav.getStagedLeavingView();
this.enteringZ = entering.index;
this.leavingZ = (leaving && leaving.index) || 0;
// create animation for the entering view's content area
this.enteringContent = new Animation(entering.viewElementRef());
this.enteringContent.before.addClass(SHOW_VIEW_CSS);
this.add(this.enteringContent);
let enteringNavbar = this.enteringNavbar = new Animation(entering.navbarRef());
this.enteringBackButton = new Animation(entering.backBtnRef());
this.enteringTitle = new Animation(entering.titleRef());
this.enteringNavbarItems = new Animation(entering.navbarItemRefs());
this.enteringNavbarBg = new Animation(entering.navbarBgRef());
if (opts.navbar !== false) {
enteringNavbar.before.addClass(SHOW_NAVBAR_CSS);
if (entering.enableBack()) {
// only animate in the back button if the entering view has it enabled
this.enteringBackButton
.before.addClass(SHOW_BACK_BUTTON)
.fadeIn();
enteringNavbar.add(this.enteringBackButton);
}
enteringNavbar
.add(this.enteringTitle)
.add(this.enteringNavbarItems.fadeIn())
.add(this.enteringNavbarBg);
this.add(enteringNavbar);
let enteringView = navCtrl.getStagedEnteringView();
if (enteringView) {
this.add( new EnteringTransition(navCtrl, enteringView, opts) );
}
this.leavingContent = new Animation(leaving && leaving.viewElementRef());
let leavingNavbar = this.leavingNavbar = new Animation(leaving && leaving.navbarRef());
this.leavingBackButton = new Animation(leaving && leaving.backBtnRef());
this.leavingTitle = new Animation(leaving && leaving.titleRef());
this.leavingNavbarItems = new Animation(leaving && leaving.navbarItemRefs());
this.leavingNavbarBg = new Animation(leaving && leaving.navbarBgRef());
if (leaving) {
// setup the leaving item if one exists (initial viewing wouldn't have a leaving item)
this.leavingContent.after.removeClass(SHOW_VIEW_CSS);
leavingNavbar.after.removeClass(SHOW_NAVBAR_CSS);
this.leavingBackButton
.after.removeClass(SHOW_BACK_BUTTON)
.fadeOut();
leavingNavbar
.add(this.leavingBackButton)
.add(this.leavingTitle)
.add(this.leavingNavbarItems.fadeOut())
.add(this.leavingNavbarBg);
this.add(this.leavingContent, leavingNavbar);
let leavingView = navCtrl.getStagedLeavingView();
if (leavingView) {
this.add( new LeavingTransition(navCtrl, leavingView, opts) );
}
}
viewWidth() {
// TODO: MAKE MORE BETTER
return this._w || (this._w = this.leaving && this.leaving.viewElementRef().nativeElement.offsetWidth);
}
/*
STATIC CLASSES
*/
static create(nav, opts = {}) {
static create(navCtrl, opts = {}) {
const name = opts.animation || 'ios';
let TransitionClass = TransitionRegistry[name];
let TransitionClass = transitionRegistry[name];
if (!TransitionClass) {
// transition wasn't found, default to a 'none' transition
// which doesn't animate anything, just shows and hides
TransitionClass = Transition;
TransitionClass = transitionRegistry.ios;
}
return new TransitionClass(nav, opts);
return new TransitionClass(navCtrl, opts);
}
static register(name, TransitionClass) {
TransitionRegistry[name] = TransitionClass;
transitionRegistry[name] = TransitionClass;
}
}
export class ViewTransition extends Animation {
constructor(navCtrl, viewCtrl, opts) {
super(null, opts);
// create animation for the entering view's content area
this.content = new Animation(viewCtrl.contentRef());
this.content.before.addClass(SHOW_VIEW_CSS);
this.add(this.content);
this.navbar = new Animation(viewCtrl.navbarRef());
this.backButton = new Animation(viewCtrl.backBtnRef());
this.title = new Animation(viewCtrl.titleRef());
this.navbarItems = new Animation(viewCtrl.navbarItemRefs());
this.navbarBg = new Animation(viewCtrl.navbarBgRef());
this.navbar
.add(this.backButton)
.add(this.title)
.add(this.navbarItems)
.add(this.navbarBg);
this.add(this.navbar);
}
}
let transitionRegistry = {};