mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-21 21:15:24 +08:00
fix(nav): flickering
This commit is contained in:
1
packages/core/src/components.d.ts
vendored
1
packages/core/src/components.d.ts
vendored
@ -3059,6 +3059,7 @@ declare global {
|
||||
}
|
||||
namespace JSXElements {
|
||||
export interface IonTabAttributes extends HTMLAttributes {
|
||||
active?: boolean;
|
||||
badge?: string;
|
||||
badgeStyle?: string;
|
||||
btnId?: string;
|
||||
|
@ -22,6 +22,7 @@ export interface Animation {
|
||||
beforeClearStyles(propertyNames: string[]): Animation;
|
||||
beforeAddRead(domReadFn: Function): Animation;
|
||||
beforeAddWrite(domWriteFn: Function): Animation;
|
||||
duringAddClass(className: string): Animation;
|
||||
afterAddClass(className: string): Animation;
|
||||
afterRemoveClass(className: string): Animation;
|
||||
afterStyles(styles: { [property: string]: any; }): Animation;
|
||||
|
@ -231,6 +231,15 @@ export class Animator {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a CSS class during the duration of the animation.
|
||||
*/
|
||||
duringAddClass(className: string): Animator {
|
||||
this.beforeAddClass(className);
|
||||
this.afterRemoveClass(className);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CSS inline styles to this animation's elements
|
||||
* before the animation begins.
|
||||
|
@ -8,6 +8,3 @@ $content-ios-font-family: $font-family-ios-base !default;
|
||||
|
||||
/// @prop - Background color of the outer content
|
||||
$content-ios-outer-background: $background-ios-color-step-50 !default;
|
||||
|
||||
/// @prop - Background color of the content when making transition
|
||||
$content-ios-transition-background: #000 !default;
|
||||
|
@ -68,7 +68,7 @@ export function canNavGoBack(nav: Nav, view?: ViewController) {
|
||||
if (!nav) {
|
||||
return false;
|
||||
}
|
||||
return nav.getPrevious(view);
|
||||
return !!nav.getPrevious(view);
|
||||
}
|
||||
|
||||
export function transitionFactory(animation: Animation): Transition {
|
||||
@ -127,20 +127,28 @@ export function destroyTransition(transitionId: number) {
|
||||
}
|
||||
|
||||
export function getHydratedTransition(name: string, config: Config, transitionId: number, emptyTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions, defaultTransitionFactory: TransitionBuilder): Promise<Transition> {
|
||||
|
||||
// Let makes sure everything is hydrated and ready to animate
|
||||
const componentReadyPromise: Promise<any>[] = [];
|
||||
if (enteringView && (enteringView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((enteringView.element as any).componentOnReady());
|
||||
}
|
||||
if (leavingView && (leavingView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((leavingView.element as any).componentOnReady());
|
||||
}
|
||||
const transitionFactory = config.get(name) as TransitionBuilder || defaultTransitionFactory;
|
||||
|
||||
return transitionFactory(emptyTransition, enteringView, leavingView, opts).then((hydratedTransition) => {
|
||||
hydratedTransition.transitionId = transitionId;
|
||||
if (!activeTransitions.has(transitionId)) {
|
||||
// sweet, this is the root transition
|
||||
activeTransitions.set(transitionId, hydratedTransition);
|
||||
} else {
|
||||
// we've got a parent transition going
|
||||
// just append this transition to the existing one
|
||||
activeTransitions.get(transitionId).add(hydratedTransition);
|
||||
}
|
||||
return hydratedTransition;
|
||||
return Promise.all(componentReadyPromise)
|
||||
.then(() => transitionFactory(emptyTransition, enteringView, leavingView, opts))
|
||||
.then((hydratedTransition) => {
|
||||
hydratedTransition.transitionId = transitionId;
|
||||
if (!activeTransitions.has(transitionId)) {
|
||||
// sweet, this is the root transition
|
||||
activeTransitions.set(transitionId, hydratedTransition);
|
||||
} else {
|
||||
// we've got a parent transition going
|
||||
// just append this transition to the existing one
|
||||
activeTransitions.get(transitionId).add(hydratedTransition);
|
||||
}
|
||||
return hydratedTransition;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Util
|
||||
// --------------------------------------------------
|
||||
@import "../../themes/util";
|
||||
|
||||
$navigation-ios-transition-background: #000 !default;
|
||||
|
||||
ion-nav {
|
||||
@include position(0);
|
||||
@ -13,10 +12,7 @@ ion-nav {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: #000;
|
||||
|
||||
contain: layout size style;
|
||||
|
||||
}
|
||||
|
||||
.ion-page {
|
||||
@ -31,3 +27,24 @@ ion-nav {
|
||||
|
||||
contain: layout size style;
|
||||
}
|
||||
|
||||
.nav-decor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.show-decor > .nav-decor {
|
||||
@include position(0, null, null, 0);
|
||||
|
||||
// when ios pages transition, the leaving page grays out
|
||||
// this is the black square behind all pages so they gray out
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
display: block;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: $navigation-ios-transition-background;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -335,6 +335,9 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
attachTo='body'
|
||||
></ion-gesture>);
|
||||
}
|
||||
if (this.mode === 'ios') {
|
||||
dom.push(<div class='nav-decor'/>);
|
||||
}
|
||||
dom.push(<slot></slot>);
|
||||
return dom;
|
||||
}
|
||||
@ -820,7 +823,8 @@ export function loadViewAndTransition(nav: Nav, enteringView: ViewController, le
|
||||
|
||||
|
||||
const emptyTransition = transitionFactory(ti.animation);
|
||||
return getHydratedTransition(animationOpts.animation, nav.config, nav.transitionId, emptyTransition, enteringView, leavingView, animationOpts, getDefaultTransition(nav.config)).then((transition) => {
|
||||
return getHydratedTransition(animationOpts.animation, nav.config, nav.transitionId, emptyTransition, enteringView, leavingView, animationOpts, getDefaultTransition(nav.config))
|
||||
.then((transition) => {
|
||||
|
||||
if (nav.sbTrns) {
|
||||
nav.sbTrns.destroy();
|
||||
@ -967,6 +971,7 @@ export function fireViewWillLifecycles(enteringView: ViewController, leavingView
|
||||
export function attachViewToDom(nav: Nav, enteringView: ViewController, ti: TransitionInstruction) {
|
||||
if (enteringView && enteringView.state === STATE_NEW) {
|
||||
return ti.delegate.attachViewToDom(nav.element, enteringView.component, enteringView.data, [], ti.escapeHatch).then((mountingData) => {
|
||||
mountingData.element.classList.add('nav-page');
|
||||
ti.mountingData = mountingData;
|
||||
Object.assign(enteringView, mountingData);
|
||||
enteringView.state = STATE_ATTACHED;
|
||||
|
@ -12,197 +12,193 @@ const OFF_OPACITY = 0.8;
|
||||
const SHOW_BACK_BTN_CSS = 'show-back-button';
|
||||
|
||||
export function buildIOSTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise<Transition> {
|
||||
const componentReadyPromise: Promise<any>[] = [];
|
||||
// Let makes sure everything is hydrated and ready to animate
|
||||
if (enteringView && (enteringView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((enteringView.element as any).componentOnReady());
|
||||
}
|
||||
if (leavingView && (leavingView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((leavingView.element as any).componentOnReady());
|
||||
// Cool we're all hydrated, and can do deep selector
|
||||
rootTransition.enteringView = enteringView;
|
||||
rootTransition.leavingView = leavingView;
|
||||
|
||||
const isRTL = document.dir === 'rtl';
|
||||
const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%';
|
||||
const OFF_LEFT = isRTL ? '33%' : '-33%';
|
||||
|
||||
rootTransition.duration(isDef(opts.duration) ? opts.duration : DURATION);
|
||||
rootTransition.easing(isDef(opts.easing) ? opts.easing : EASING);
|
||||
|
||||
|
||||
rootTransition.addElement(enteringView.element);
|
||||
rootTransition.beforeRemoveClass('hide-page');
|
||||
|
||||
if (leavingView) {
|
||||
const navEl = leavingView.element.closest('ion-nav');
|
||||
if (navEl) {
|
||||
const navDecor = rootTransition.create();
|
||||
navDecor.addElement(navEl).duringAddClass('show-decor');
|
||||
rootTransition.add(navDecor);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(componentReadyPromise).then(() => {
|
||||
// Cool we're all hydrated, and can do deep selector
|
||||
rootTransition.enteringView = enteringView;
|
||||
rootTransition.leavingView = leavingView;
|
||||
const backDirection = (opts.direction === 'back');
|
||||
// setting up enter view
|
||||
if (enteringView) {
|
||||
|
||||
const isRTL = document.dir === 'rtl';
|
||||
const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%';
|
||||
const OFF_LEFT = isRTL ? '33%' : '-33%';
|
||||
const enteringContent = rootTransition.create();
|
||||
enteringContent.addElement(enteringView.element.querySelector('ion-content'));
|
||||
enteringContent.addElement(enteringView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *'));
|
||||
rootTransition.add(enteringContent);
|
||||
|
||||
rootTransition.duration(isDef(opts.duration) ? opts.duration : DURATION);
|
||||
rootTransition.easing(isDef(opts.easing) ? opts.easing : EASING);
|
||||
if (backDirection) {
|
||||
enteringContent
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true)
|
||||
.fromTo(OPACITY, OFF_OPACITY, 1, true);
|
||||
} else {
|
||||
// entering content, forward direction
|
||||
enteringContent
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true);
|
||||
|
||||
}
|
||||
|
||||
rootTransition.addElement(enteringView.element);
|
||||
rootTransition.beforeRemoveClass('hide-page');
|
||||
const enteringToolBarEle = enteringView.element.querySelector('ion-toolbar');
|
||||
if (enteringToolBarEle) {
|
||||
const enteringToolBar = rootTransition.create();
|
||||
enteringToolBar.addElement(enteringToolBarEle);
|
||||
rootTransition.add(enteringToolBar);
|
||||
|
||||
const backDirection = (opts.direction === 'back');
|
||||
const enteringTitle = rootTransition.create();
|
||||
enteringTitle.addElement(enteringToolBarEle.querySelector('ion-title'));
|
||||
|
||||
// setting up enter view
|
||||
if (enteringView) {
|
||||
const enteringToolBarItems = rootTransition.create();
|
||||
enteringToolBarItems.addElement(enteringToolBarEle.querySelectorAll('ion-buttons,[menuToggle]'));
|
||||
|
||||
const enteringContent = rootTransition.create();
|
||||
enteringContent.addElement(enteringView.element.querySelector('ion-content'));
|
||||
enteringContent.addElement(enteringView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *'));
|
||||
rootTransition.add(enteringContent);
|
||||
const enteringToolBarBg = rootTransition.create();
|
||||
enteringToolBarBg.addElement(enteringToolBarEle.querySelector('.toolbar-background'));
|
||||
|
||||
const enteringBackButton = rootTransition.create();
|
||||
enteringBackButton.addElement(enteringToolBarEle.querySelector('.back-button'));
|
||||
|
||||
enteringToolBar
|
||||
.add(enteringTitle)
|
||||
.add(enteringToolBarItems)
|
||||
.add(enteringToolBarBg)
|
||||
.add(enteringBackButton);
|
||||
|
||||
enteringTitle.fromTo(OPACITY, 0.01, 1, true);
|
||||
enteringToolBarItems.fromTo(OPACITY, 0.01, 1, true);
|
||||
|
||||
if (backDirection) {
|
||||
enteringContent
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true)
|
||||
.fromTo(OPACITY, OFF_OPACITY, 1, true);
|
||||
enteringTitle.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true);
|
||||
|
||||
if (canNavGoBack(enteringView.nav, enteringView)) {
|
||||
// back direction, entering page has a back button
|
||||
enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS).fromTo(OPACITY, 0.01, 1, true);
|
||||
}
|
||||
} else {
|
||||
// entering content, forward direction
|
||||
enteringContent
|
||||
// entering toolbar, forward direction
|
||||
enteringTitle.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true);
|
||||
|
||||
enteringToolBarBg
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true);
|
||||
|
||||
}
|
||||
if (canNavGoBack(enteringView.nav, enteringView)) {
|
||||
|
||||
const enteringToolBarEle = enteringView.element.querySelector('ion-toolbar');
|
||||
if (enteringToolBarEle) {
|
||||
const enteringToolBar = rootTransition.create();
|
||||
enteringToolBar.addElement(enteringToolBarEle);
|
||||
rootTransition.add(enteringToolBar);
|
||||
// forward direction, entering page has a back button
|
||||
enteringBackButton
|
||||
.beforeAddClass(SHOW_BACK_BTN_CSS)
|
||||
.fromTo(OPACITY, 0.01, 1, true);
|
||||
|
||||
const enteringTitle = rootTransition.create();
|
||||
enteringTitle.addElement(enteringToolBarEle.querySelector('ion-title'));
|
||||
|
||||
const enteringToolBarItems = rootTransition.create();
|
||||
enteringToolBarItems.addElement(enteringToolBarEle.querySelectorAll('ion-buttons,[menuToggle]'));
|
||||
const enteringBackBtnText = rootTransition.create();
|
||||
enteringBackBtnText.addElement(enteringToolBarEle.querySelector('.back-button .button-text'));
|
||||
|
||||
const enteringToolBarBg = rootTransition.create();
|
||||
enteringToolBarBg.addElement(enteringToolBarEle.querySelector('.toolbar-background'));
|
||||
|
||||
const enteringBackButton = rootTransition.create();
|
||||
enteringBackButton.addElement(enteringToolBarEle.querySelector('.back-button'));
|
||||
|
||||
enteringToolBar
|
||||
.add(enteringTitle)
|
||||
.add(enteringToolBarItems)
|
||||
.add(enteringToolBarBg)
|
||||
.add(enteringBackButton);
|
||||
|
||||
enteringTitle.fromTo(OPACITY, 0.01, 1, true);
|
||||
enteringToolBarItems.fromTo(OPACITY, 0.01, 1, true);
|
||||
|
||||
if (backDirection) {
|
||||
enteringTitle.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true);
|
||||
|
||||
if (canNavGoBack(enteringView.nav, enteringView)) {
|
||||
// back direction, entering page has a back button
|
||||
enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS).fromTo(OPACITY, 0.01, 1, true);
|
||||
}
|
||||
enteringBackBtnText.fromTo(TRANSLATEX, (isRTL ? '-100px' : '100px'), '0px');
|
||||
enteringToolBar.add(enteringBackBtnText);
|
||||
} else {
|
||||
// entering toolbar, forward direction
|
||||
enteringTitle.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true);
|
||||
|
||||
enteringToolBarBg
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true);
|
||||
|
||||
if (canNavGoBack(enteringView.nav, enteringView)) {
|
||||
|
||||
// forward direction, entering page has a back button
|
||||
enteringBackButton
|
||||
.beforeAddClass(SHOW_BACK_BTN_CSS)
|
||||
.fromTo(OPACITY, 0.01, 1, true);
|
||||
|
||||
|
||||
const enteringBackBtnText = rootTransition.create();
|
||||
enteringBackBtnText.addElement(enteringToolBarEle.querySelector('.back-button .button-text'));
|
||||
|
||||
enteringBackBtnText.fromTo(TRANSLATEX, (isRTL ? '-100px' : '100px'), '0px');
|
||||
enteringToolBar.add(enteringBackBtnText);
|
||||
} else {
|
||||
enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS);
|
||||
}
|
||||
enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup leaving view
|
||||
if (leavingView) {
|
||||
// setup leaving view
|
||||
if (leavingView) {
|
||||
|
||||
const leavingContent = rootTransition.create();
|
||||
leavingContent.addElement(leavingView.element.querySelector('ion-content'));
|
||||
leavingContent.addElement(leavingView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *'));
|
||||
rootTransition.add(leavingContent);
|
||||
const leavingContent = rootTransition.create();
|
||||
leavingContent.addElement(leavingView.element.querySelector('ion-content'));
|
||||
leavingContent.addElement(leavingView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *'));
|
||||
rootTransition.add(leavingContent);
|
||||
|
||||
if (backDirection) {
|
||||
// leaving content, back direction
|
||||
leavingContent
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%'));
|
||||
|
||||
|
||||
} else {
|
||||
// leaving content, forward direction
|
||||
leavingContent
|
||||
.fromTo(TRANSLATEX, CENTER, OFF_LEFT, true)
|
||||
.fromTo(OPACITY, 1, OFF_OPACITY, true);
|
||||
}
|
||||
|
||||
const leavingToolBarEle = leavingView.element.querySelector('ion-toolbar');
|
||||
if (leavingToolBarEle) {
|
||||
const leavingToolBar = rootTransition.create();
|
||||
leavingToolBar.addElement(leavingToolBarEle);
|
||||
|
||||
const leavingTitle = rootTransition.create();
|
||||
leavingTitle.addElement(leavingToolBarEle.querySelector('ion-title'));
|
||||
|
||||
const leavingToolBarItems = rootTransition.create();
|
||||
leavingToolBarItems.addElement(leavingToolBarEle.querySelectorAll('ion-buttons,[menuToggle]'));
|
||||
|
||||
const leavingToolBarBg = rootTransition.create();
|
||||
leavingToolBarBg.addElement(leavingToolBarEle.querySelector('.toolbar-background'));
|
||||
|
||||
const leavingBackButton = rootTransition.create();
|
||||
leavingBackButton.addElement(leavingToolBarEle.querySelector('.back-button'));
|
||||
|
||||
leavingToolBar
|
||||
.add(leavingTitle)
|
||||
.add(leavingToolBarItems)
|
||||
.add(leavingBackButton)
|
||||
.add(leavingToolBarBg);
|
||||
|
||||
rootTransition.add(leavingToolBar);
|
||||
|
||||
// fade out leaving toolbar items
|
||||
leavingBackButton.fromTo(OPACITY, 0.99, 0, true);
|
||||
leavingTitle.fromTo(OPACITY, 0.99, 0, true);
|
||||
leavingToolBarItems.fromTo(OPACITY, 0.99, 0, true);
|
||||
|
||||
if (backDirection) {
|
||||
// leaving content, back direction
|
||||
leavingContent
|
||||
// leaving toolbar, back direction
|
||||
leavingTitle.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%'));
|
||||
|
||||
// leaving toolbar, back direction, and there's no entering toolbar
|
||||
// should just slide out, no fading out
|
||||
leavingToolBarBg
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%'));
|
||||
|
||||
const leavingBackBtnText = rootTransition.create();
|
||||
leavingBackBtnText.addElement(leavingToolBarEle.querySelector('.back-button .button-text'));
|
||||
leavingBackBtnText.fromTo(TRANSLATEX, CENTER, (isRTL ? -300 : 300) + 'px');
|
||||
leavingToolBar.add(leavingBackBtnText);
|
||||
|
||||
} else {
|
||||
// leaving content, forward direction
|
||||
leavingContent
|
||||
.fromTo(TRANSLATEX, CENTER, OFF_LEFT, true)
|
||||
.fromTo(OPACITY, 1, OFF_OPACITY, true);
|
||||
}
|
||||
// leaving toolbar, forward direction
|
||||
leavingTitle
|
||||
.fromTo(TRANSLATEX, CENTER, OFF_LEFT)
|
||||
.afterClearStyles([TRANSFORM]);
|
||||
|
||||
const leavingToolBarEle = leavingView.element.querySelector('ion-toolbar');
|
||||
if (leavingToolBarEle) {
|
||||
const leavingToolBar = rootTransition.create();
|
||||
leavingToolBar.addElement(leavingToolBarEle);
|
||||
|
||||
const leavingTitle = rootTransition.create();
|
||||
leavingTitle.addElement(leavingToolBarEle.querySelector('ion-title'));
|
||||
|
||||
const leavingToolBarItems = rootTransition.create();
|
||||
leavingToolBarItems.addElement(leavingToolBarEle.querySelectorAll('ion-buttons,[menuToggle]'));
|
||||
|
||||
const leavingToolBarBg = rootTransition.create();
|
||||
leavingToolBarBg.addElement(leavingToolBarEle.querySelector('.toolbar-background'));
|
||||
|
||||
const leavingBackButton = rootTransition.create();
|
||||
leavingBackButton.addElement(leavingToolBarEle.querySelector('.back-button'));
|
||||
|
||||
leavingToolBar
|
||||
.add(leavingTitle)
|
||||
.add(leavingToolBarItems)
|
||||
.add(leavingBackButton)
|
||||
.add(leavingToolBarBg);
|
||||
|
||||
rootTransition.add(leavingToolBar);
|
||||
|
||||
// fade out leaving toolbar items
|
||||
leavingBackButton.fromTo(OPACITY, 0.99, 0, true);
|
||||
leavingTitle.fromTo(OPACITY, 0.99, 0, true);
|
||||
leavingToolBarItems.fromTo(OPACITY, 0.99, 0, true);
|
||||
|
||||
if (backDirection) {
|
||||
// leaving toolbar, back direction
|
||||
leavingTitle.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%'));
|
||||
|
||||
// leaving toolbar, back direction, and there's no entering toolbar
|
||||
// should just slide out, no fading out
|
||||
leavingToolBarBg
|
||||
.beforeClearStyles([OPACITY])
|
||||
.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%'));
|
||||
|
||||
const leavingBackBtnText = rootTransition.create();
|
||||
leavingBackBtnText.addElement(leavingToolBarEle.querySelector('.back-button .button-text'));
|
||||
leavingBackBtnText.fromTo(TRANSLATEX, CENTER, (isRTL ? -300 : 300) + 'px');
|
||||
leavingToolBar.add(leavingBackBtnText);
|
||||
|
||||
} else {
|
||||
// leaving toolbar, forward direction
|
||||
leavingTitle
|
||||
.fromTo(TRANSLATEX, CENTER, OFF_LEFT)
|
||||
.afterClearStyles([TRANSFORM]);
|
||||
|
||||
leavingBackButton.afterClearStyles([OPACITY]);
|
||||
leavingTitle.afterClearStyles([OPACITY]);
|
||||
leavingToolBarItems.afterClearStyles([OPACITY]);
|
||||
}
|
||||
leavingBackButton.afterClearStyles([OPACITY]);
|
||||
leavingTitle.afterClearStyles([OPACITY]);
|
||||
leavingToolBarItems.afterClearStyles([OPACITY]);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the rootTransition promise
|
||||
return rootTransition;
|
||||
});
|
||||
}
|
||||
// Return the rootTransition promise
|
||||
return Promise.resolve(rootTransition);
|
||||
}
|
||||
|
@ -9,15 +9,6 @@ const SHOW_BACK_BTN_CSS = 'show-back-button';
|
||||
|
||||
export function buildMdTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise<Transition> {
|
||||
|
||||
const componentReadyPromise: Promise<any>[] = [];
|
||||
if (enteringView && (enteringView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((enteringView.element as any).componentOnReady());
|
||||
}
|
||||
if (leavingView && (leavingView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((leavingView.element as any).componentOnReady());
|
||||
}
|
||||
|
||||
return Promise.all(componentReadyPromise).then(() => {
|
||||
rootTransition.enteringView = enteringView;
|
||||
rootTransition.leavingView = leavingView;
|
||||
|
||||
@ -68,10 +59,7 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View
|
||||
rootTransition.add(leavingPage.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM).fromTo('opacity', 1, 0));
|
||||
}
|
||||
|
||||
return rootTransition;
|
||||
|
||||
});
|
||||
|
||||
return Promise.resolve(rootTransition);
|
||||
}
|
||||
|
||||
function getIonPageElement(element: HTMLElement) {
|
||||
|
@ -32,7 +32,7 @@ export class Router {
|
||||
}
|
||||
|
||||
@Listen('window:popstate')
|
||||
protected onURLHashChanged() {
|
||||
protected onPopState() {
|
||||
if (window.history.state === null) {
|
||||
this.state++;
|
||||
window.history.replaceState(this.state, document.title, document.location.href);
|
||||
|
@ -50,6 +50,11 @@ export class Tabs {
|
||||
|
||||
## Properties
|
||||
|
||||
#### active
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### badge
|
||||
|
||||
string
|
||||
@ -131,6 +136,11 @@ The title of the tab button.
|
||||
|
||||
## Attributes
|
||||
|
||||
#### active
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### badge
|
||||
|
||||
string
|
||||
@ -222,7 +232,7 @@ Emitted when the current tab is selected.
|
||||
#### getRouteId()
|
||||
|
||||
|
||||
#### setActive()
|
||||
#### prepareActive()
|
||||
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ export class Tab {
|
||||
@Element() el: HTMLElement;
|
||||
|
||||
@State() init = false;
|
||||
@State() active = false;
|
||||
@Prop() active = false;
|
||||
|
||||
/**
|
||||
* Set the root page for this tab.
|
||||
@ -79,11 +79,7 @@ export class Tab {
|
||||
@Event() ionSelect: EventEmitter<void>;
|
||||
|
||||
@Method()
|
||||
setActive(active: boolean): Promise<any> {
|
||||
this.active = active;
|
||||
if (!active) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
prepareActive(): Promise<any> {
|
||||
if (this.loaded) {
|
||||
return this.configChildgNav();
|
||||
}
|
||||
@ -140,13 +136,13 @@ export class Tab {
|
||||
}
|
||||
|
||||
hostData() {
|
||||
const visible = this.active && this.selected;
|
||||
const hidden = !this.active || !this.selected;
|
||||
return {
|
||||
'aria-hidden': !visible,
|
||||
'aria-hidden': hidden,
|
||||
'aria-labelledby': this.btnId,
|
||||
'role': 'tabpanel',
|
||||
class: {
|
||||
'show-tab': visible
|
||||
'show-tab': this.active
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
|
||||
import { Config, NavEventDetail, NavOutlet } from '../../index';
|
||||
|
||||
import { ensureExternalRounterController } from '../../utils/helpers';
|
||||
import { asyncRaf, ensureExternalRounterController } from '../../utils/helpers';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -121,15 +121,17 @@ export class Tabs implements NavOutlet {
|
||||
const leavingTab = this.selectedTab;
|
||||
this.selectedTab = selectedTab;
|
||||
|
||||
let promise = selectedTab.setActive(true);
|
||||
if (leavingTab && leavingTab !== selectedTab) {
|
||||
promise = promise.then(() => leavingTab.setActive(false));
|
||||
}
|
||||
|
||||
return promise.then(() => {
|
||||
this.ionChange.emit(selectedTab);
|
||||
this.ionNavChanged.emit({isPop: false});
|
||||
});
|
||||
return selectedTab.prepareActive()
|
||||
.then(() => selectedTab.active = true)
|
||||
.then(() => asyncRaf())
|
||||
.then(() => {
|
||||
if (leavingTab) {
|
||||
leavingTab.active = false;
|
||||
}
|
||||
this.ionChange.emit(selectedTab);
|
||||
this.ionNavChanged.emit({isPop: false});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,7 +211,7 @@ export class Tabs implements NavOutlet {
|
||||
tab.selected = false;
|
||||
}
|
||||
}
|
||||
const promise = selectedTab ? selectedTab.setActive(true) : Promise.resolve();
|
||||
const promise = selectedTab ? selectedTab.prepareActive() : Promise.resolve();
|
||||
return promise.then(() => {
|
||||
this.selectedTab = selectedTab;
|
||||
if (selectedTab) {
|
||||
|
@ -295,6 +295,10 @@ export function debounce(func: Function, wait = 0) {
|
||||
};
|
||||
}
|
||||
|
||||
export function asyncRaf(): Promise<number> {
|
||||
return new Promise(resolve => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
export function getNavAsChildIfExists(element: HTMLElement): HTMLIonNavElement|null {
|
||||
for (let i = 0; i < element.children.length; i++) {
|
||||
if (element.children[i].tagName.toLowerCase() === 'ion-nav') {
|
||||
|
Reference in New Issue
Block a user