integrate animations with framework components

This commit is contained in:
Liam DeBeasi
2019-07-23 16:22:16 -04:00
parent b6392af33f
commit fbf9661880
39 changed files with 480 additions and 481 deletions

View File

@@ -1387,7 +1387,7 @@ export namespace Components {
/**
* Registers a new animation that can be used with any `ion-menu` by passing the name of the animation in its `type` property.
*/
'registerAnimation': (name: string, animation: AnimationBuilder) => Promise<void>;
'registerAnimation': (name: string, animation: any) => Promise<void>;
/**
* Enable or disable the ability to swipe open the menu.
*/

View File

@@ -1,7 +1,7 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Method, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { ActionSheetButton, Animation, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
import { BACKDROP, dismiss, eventMethod, isCancel, present, safeCall } from '../../utils/overlays';
import { getClassMap } from '../../utils/theme';
@@ -24,7 +24,7 @@ import { mdLeaveAnimation } from './animations/md.leave';
export class ActionSheet implements ComponentInterface, OverlayInterface {
presented = false;
animation?: Animation;
animation?: any;
mode = getIonMode(this);
@Element() el!: HTMLElement;

View File

@@ -1,27 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Action Sheet Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.4);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.action-sheet-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper'))
.fromTo('transform', 'translateY(100%)', 'translateY(0%)');
backdropAnimation.fromTo('opacity', 0.01, 0.4);
wrapperAnimation.fromTo('translateY', '100%', '0%');
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(400)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,27 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Action Sheet Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.4, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.action-sheet-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper'))
.fromTo('transform', 'translateY(0%)', 'translateY(100%)');
backdropAnimation.fromTo('opacity', 0.4, 0);
wrapperAnimation.fromTo('translateY', '0%', '100%');
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(450)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,27 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* MD Action Sheet Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.32);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.action-sheet-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper'))
.fromTo('transform', 'translateY(100%)', 'translateY(0%)');
backdropAnimation.fromTo('opacity', 0.01, 0.32);
wrapperAnimation.fromTo('translateY', '100%', '0%');
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(400)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,27 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* MD Action Sheet Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const baseAnimation = new AnimationC();
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.32, 0);
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper'))
.fromTo('transform', 'translateY(0%)', 'translateY(100%)');
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.action-sheet-wrapper'));
backdropAnimation.fromTo('opacity', 0.32, 0);
wrapperAnimation.fromTo('translateY', '0%', '100%');
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(450)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,27 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Alert Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.3);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.alert-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.01, transform: 'scale(1.1)' },
{ offset: 1, opacity: 1, transform: 'scale(1)' }
]);
backdropAnimation.fromTo('opacity', 0.01, 0.3);
wrapperAnimation.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,27 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Alert Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.3, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.alert-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.99, transform: 'scale(1)' },
{ offset: 1, opacity: 0, transform: 'scale(0.9)' }
]);
backdropAnimation.fromTo('opacity', 0.3, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
const ani = baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation);
return Promise.resolve(ani);
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Alert Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.32);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.alert-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.01, transform: 'scale(0.9)' },
{ offset: 1, opacity: 1, transform: 'scale(1)' }
]);
backdropAnimation.fromTo('opacity', 0.01, 0.32);
wrapperAnimation.fromTo('opacity', 0.01, 1).fromTo('scale', 0.9, 1);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(150)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Alert Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.32, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.alert-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper'))
.fromTo('opacity', 0.99, 0);
backdropAnimation.fromTo('opacity', 0.32, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(150)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,26 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Loading Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.3);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.loading-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.loading-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.01, transform: 'scale(1.1)' },
{ offset: 1, opacity: 1, transform: 'scale(1)' }
]);
backdropAnimation.fromTo('opacity', 0.01, 0.3);
wrapperAnimation.fromTo('opacity', 0.01, 1)
.fromTo('scale', 1.1, 1);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,26 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Loading Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.3, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.loading-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.loading-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.99, transform: 'scale(1)' },
{ offset: 1, opacity: 0, transform: 'scale(0.9)' }
]);
backdropAnimation.fromTo('opacity', 0.3, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0)
.fromTo('scale', 1, 0.9);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Loading Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.32);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.loading-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.loading-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.01, transform: 'scale(1.1)' },
{ offset: 1, opacity: 1, transform: 'scale(1)' }
]);
backdropAnimation.fromTo('opacity', 0.01, 0.32);
wrapperAnimation.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Loading Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.32, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.loading-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.loading-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.99, transform: 'scale(1)' },
{ offset: 1, opacity: 0, transform: 'scale(0.9)' }
]);
backdropAnimation.fromTo('opacity', 0.32, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-in-out')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,4 +1,4 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* baseAnimation
@@ -6,16 +6,18 @@ import { Animation } from '../../../interface';
* type will provide their own animations for open and close
* and registers itself with Menu.
*/
export const baseAnimation = (AnimationC: Animation): Promise<Animation> => {
export const baseAnimation = (): Animation => {
// https://material.io/guidelines/motion/movement.html#movement-movement-in-out-of-screen-bounds
// https://material.io/guidelines/motion/duration-easing.html#duration-easing-natural-easing-curves
// "Apply the sharp curve to items temporarily leaving the screen that may return
// from the same exit point. When they return, use the deceleration curve. On mobile,
// this transition typically occurs over 300ms" -- MD Motion Guide
return Promise.resolve(
new AnimationC()
return createAnimation()
.easing('cubic-bezier(0.0, 0.0, 0.2, 1)') // Deceleration curve (Entering the screen)
.easingReverse('cubic-bezier(0.4, 0.0, 0.6, 1)') // Sharp curve (Temporarily leaving the screen)
.duration(300));
.duration(300);
};
// cubic-bezier(0.0, 0.0, 0.2, 1)'//entering
// 'cubic-bezier(0.4, 0.0, 0.6, 1)'//leaving

View File

@@ -1,17 +1,22 @@
import { Animation, MenuI } from '../../../interface';
import { MenuI } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
import { baseAnimation } from './base';
const BOX_SHADOW_WIDTH = 8;
/**
* Menu Overlay Type
* The menu slides over the content. The content
* itself, which is under the menu, does not move.
*/
export const menuOverlayAnimation = (AnimationC: Animation, _: HTMLElement, menu: MenuI): Promise<Animation> => {
export const menuOverlayAnimation = (menu: MenuI): Animation => {
let closedX: string;
let openedX: string;
const BOX_SHADOW_WIDTH = 8;
const width = menu.width + BOX_SHADOW_WIDTH;
const menuAnimation = createAnimation();
const backdropAnimation = createAnimation();
if (menu.isEndSide) {
// right side
closedX = width + 'px';
@@ -23,16 +28,13 @@ export const menuOverlayAnimation = (AnimationC: Animation, _: HTMLElement, menu
openedX = '0px';
}
const menuAnimation = new AnimationC()
menuAnimation
.addElement(menu.menuInnerEl)
.fromTo('translateX', closedX, openedX);
.fromTo('transform', `translateX(${closedX})`, `translateX(${openedX})`);
const backdropAnimation = new AnimationC()
backdropAnimation
.addElement(menu.backdropEl)
.fromTo('opacity', 0.01, 0.32);
return baseAnimation(AnimationC).then(animation => {
return animation.add(menuAnimation)
.add(backdropAnimation);
});
return baseAnimation().addAnimation([menuAnimation, backdropAnimation]);
};

View File

@@ -1,4 +1,5 @@
import { Animation, MenuI } from '../../../interface';
import { MenuI } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
import { baseAnimation } from './base';
@@ -7,10 +8,10 @@ import { baseAnimation } from './base';
* The content slides over to reveal the menu underneath.
* The menu itself also slides over to reveal its bad self.
*/
export const menuPushAnimation = (AnimationC: Animation, _: HTMLElement, menu: MenuI): Promise<Animation> => {
export const menuPushAnimation = (menu: MenuI): Animation => {
let contentOpenedX: string;
let menuClosedX: string;
const width = menu.width;
if (menu.isEndSide) {
@@ -21,21 +22,18 @@ export const menuPushAnimation = (AnimationC: Animation, _: HTMLElement, menu: M
contentOpenedX = width + 'px';
menuClosedX = -width + 'px';
}
const menuAnimation = new AnimationC()
const menuAnimation = createAnimation()
.addElement(menu.menuInnerEl)
.fromTo('translateX', menuClosedX, '0px');
.fromTo('transform', `translateX(${menuClosedX})`, 'translateX(0px)');
const contentAnimation = new AnimationC()
const contentAnimation = createAnimation()
.addElement(menu.contentEl)
.fromTo('translateX', '0px', contentOpenedX);
.fromTo('transform', 'translateX(0px)', `translateX(${contentOpenedX})`);
const backdropAnimation = new AnimationC()
const backdropAnimation = createAnimation()
.addElement(menu.backdropEl)
.fromTo('opacity', 0.01, 0.32);
return baseAnimation(AnimationC).then(animation => {
return animation.add(menuAnimation)
.add(backdropAnimation)
.add(contentAnimation);
});
return baseAnimation().addAnimation([menuAnimation, backdropAnimation, contentAnimation]);
};

View File

@@ -1,4 +1,5 @@
import { Animation, MenuI } from '../../../interface';
import { MenuI } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
import { baseAnimation } from './base';
@@ -7,14 +8,12 @@ import { baseAnimation } from './base';
* The content slides over to reveal the menu underneath.
* The menu itself, which is under the content, does not move.
*/
export const menuRevealAnimation = (AnimationC: Animation, _: HTMLElement, menu: MenuI): Promise<Animation> => {
export const menuRevealAnimation = (menu: MenuI): Animation => {
const openedX = (menu.width * (menu.isEndSide ? -1 : 1)) + 'px';
const contentOpen = new AnimationC()
const contentOpen = createAnimation()
.addElement(menu.contentEl)
.fromTo('translateX', '0px', openedX);
.fromTo('transform', 'translateX(0px)', `translateX(${openedX})`);
return baseAnimation(AnimationC).then(animation => {
return animation.add(contentOpen);
});
return baseAnimation().addAnimation(contentOpen);
};

View File

@@ -1,7 +1,7 @@
import { Build, Component, Method } from '@stencil/core';
import { config } from '../../global/config';
import { Animation, AnimationBuilder, MenuControllerI, MenuI } from '../../interface';
import { AnimationBuilder, MenuControllerI, MenuI } from '../../interface';
import { menuOverlayAnimation } from './animations/overlay';
import { menuPushAnimation } from './animations/push';
@@ -226,7 +226,7 @@ export class MenuController implements MenuControllerI {
* @param animation The animation function to register.
*/
@Method()
async registerAnimation(name: string, animation: AnimationBuilder) {
async registerAnimation(name: string, animation: any) {
this.menuAnimations.set(name, animation);
}
@@ -278,13 +278,14 @@ export class MenuController implements MenuControllerI {
return menu._setOpen(shouldOpen, animated);
}
async _createAnimation(type: string, menuCmp: MenuI): Promise<Animation> {
const animationBuilder = this.menuAnimations.get(type);
async _createAnimation(type: string, menuCmp: MenuI): Promise<any> {
const animationBuilder = this.menuAnimations.get(type) as any;
if (!animationBuilder) {
throw new Error('animation not registered');
}
const animation = await import('../../utils/animation')
.then(mod => mod.create(animationBuilder, null, menuCmp));
const animation = animationBuilder(menuCmp);
if (!config.getBoolean('animated', true)) {
animation.duration(0);
}

View File

@@ -2,7 +2,7 @@ import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Lis
import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
import { Animation, Gesture, GestureDetail, MenuChangeEventDetail, MenuControllerI, MenuI, Side } from '../../interface';
import { Gesture, GestureDetail, MenuChangeEventDetail, MenuControllerI, MenuI, Side } from '../../interface';
import { GESTURE_CONTROLLER } from '../../utils/gesture';
import { assert, isEndSide as isEnd } from '../../utils/helpers';
@@ -16,7 +16,7 @@ import { assert, isEndSide as isEnd } from '../../utils/helpers';
})
export class Menu implements ComponentInterface, MenuI {
private animation?: Animation;
private animation?: any;
private lastOnEnd = 0;
private gesture?: Gesture;
private blocker = GESTURE_CONTROLLER.createBlocker({ disableScroll: true });
@@ -312,7 +312,13 @@ export class Menu implements ComponentInterface, MenuI {
}
private async startAnimation(shouldOpen: boolean, animated: boolean): Promise<void> {
const ani = this.animation!.reverse(!shouldOpen);
const isReversed = !shouldOpen;
console.log('play', isReversed);
const ani = this.animation!
.direction((isReversed) ? 'reverse' : 'normal')
.easing((isReversed) ? 'cubic-bezier(0.4, 0.0, 0.6, 1)' : 'cubic-bezier(0.0, 0.0, 0.2, 1)');
if (animated) {
await ani.playAsync();
} else {
@@ -358,7 +364,9 @@ export class Menu implements ComponentInterface, MenuI {
}
// the cloned animation should not use an easing curve during seek
this.animation.reverse(this._isOpen).progressStart();
this.animation
.direction('reverse')
.progressStart(true);
}
private onMove(detail: GestureDetail) {
@@ -492,7 +500,7 @@ export class Menu implements ComponentInterface, MenuI {
assert(this._isOpen, 'menu cannot be closed');
this.isAnimating = true;
const ani = this.animation!.reverse(true);
const ani = this.animation!.direction('reverse');
ani.playSync();
this.afterAnimation(false);
}

View File

@@ -15,7 +15,7 @@
<body>
<ion-app>
<ion-menu side="start" menu-id="first" id="start-menu">
<ion-menu side="start" type="reveal" menu-id="first" id="start-menu">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Start Menu</ion-title>
@@ -32,7 +32,7 @@
</ion-content>
</ion-menu>
<ion-menu side="start" menu-id="custom" class="my-custom-menu" id="custom-menu">
<ion-menu side="start" type="overlay" menu-id="custom" class="my-custom-menu" id="custom-menu">
<ion-header>
<ion-toolbar color="tertiary">
<ion-title>Custom Menu</ion-title>

View File

@@ -1,29 +1,28 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Modal Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.4);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.modal-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.modal-wrapper'))
.beforeStyles({ 'opacity': 1 })
.fromTo('transform', 'translateY(100%)', 'translateY(0%)');
wrapperAnimation.beforeStyles({ 'opacity': 1 })
.fromTo('translateY', '100%', '0%');
backdropAnimation.fromTo('opacity', 0.01, 0.4);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(400)
.beforeAddClass('show-modal')
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};
/**

View File

@@ -1,28 +1,27 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Modal Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
const wrapperAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const wrapperEl = baseEl.querySelector('.modal-wrapper');
wrapperAnimation.addElement(wrapperEl);
const wrapperElRect = wrapperEl!.getBoundingClientRect();
wrapperAnimation.beforeStyles({ 'opacity': 1 })
.fromTo('translateY', '0%', `${(baseEl.ownerDocument as any).defaultView.innerHeight - wrapperElRect.top}px`);
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.4, 0.0);
backdropAnimation.fromTo('opacity', 0.4, 0.0);
wrapperAnimation
.addElement(wrapperEl)
.beforeStyles({ 'opacity': 1 })
.fromTo('transform', 'translateY(0%)', `translateY(${(baseEl.ownerDocument as any).defaultView.innerHeight - wrapperElRect.top}px)`);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease-out')
.duration(250)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,28 +1,28 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Modal Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.modal-wrapper'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.32);
wrapperAnimation
.fromTo('opacity', 0.01, 1)
.fromTo('translateY', '40px', '0px');
.addElement(baseEl.querySelector('.modal-wrapper'))
.keyframes([
{ offset: 0, opacity: 0.01, transform: 'translateY(40px)' },
{ offset: 1, opacity: 1, transform: 'translateY(0px)' }
]);
backdropAnimation.fromTo('opacity', 0.01, 0.32);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(280)
.beforeAddClass('show-modal')
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,28 +1,28 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Modal Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
const wrapperAnimation = new AnimationC();
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const wrapperEl = baseEl.querySelector('.modal-wrapper');
wrapperAnimation.addElement(wrapperEl);
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.32, 0.0);
wrapperAnimation
.fromTo('opacity', 0.99, 0)
.fromTo('translateY', '0px', '40px');
.addElement(wrapperEl)
.keyframes([
{ offset: 0, opacity: 0.99, transform: 'translateY(0px)' },
{ offset: 1, opacity: 0, transform: 'translateY(40px)' }
]);
backdropAnimation.fromTo('opacity', 0.32, 0.0);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.47,0,0.745,0.715)')
.duration(200)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Picker Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.26);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.picker-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.picker-wrapper'))
.fromTo('transform', 'translateY(100%)', 'translateY(0%)');
backdropAnimation.fromTo('opacity', 0.01, 0.26);
wrapperAnimation.fromTo('translateY', '100%', '0%');
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(400)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,25 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Picker Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.26, 0.01);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.picker-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.picker-wrapper'))
.fromTo('transform', 'translateY(0%)', 'translateY(100%)');
backdropAnimation.fromTo('opacity', 0.26, 0.01);
wrapperAnimation.fromTo('translateY', '0%', '100%');
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(400)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,9 +1,9 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Popover Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement, ev?: Event): Promise<Animation> => {
export const iosEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation => {
let originY = 'top';
let originX = 'left';
@@ -97,22 +97,23 @@ export const iosEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement, ev
contentEl.style.transformOrigin = originY + ' ' + originX;
const baseAnimation = new AnimationC();
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation.fromTo('opacity', 0.01, 0.08);
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.08);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.popover-wrapper'));
wrapperAnimation.fromTo('opacity', 0.01, 1);
wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper'))
.fromTo('opacity', 0.01, 1);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(100)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};
const POPOVER_IOS_BODY_PADDING = 5;

View File

@@ -1,24 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Popover Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.08, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.popover-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper'))
.fromTo('opacity', 0.99, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0);
backdropAnimation.fromTo('opacity', 0.08, 0);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(500)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,9 +1,10 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Popover Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement, ev?: Event): Promise<Animation> => {
export const mdEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation => {
const POPOVER_MD_BODY_PADDING = 12;
const doc = (baseEl.ownerDocument as any);
const isRTL = doc.dir === 'rtl';
@@ -76,36 +77,36 @@ export const mdEnterAnimation = (AnimationC: Animation, baseEl: HTMLElement, ev?
contentEl.style.bottom = POPOVER_MD_BODY_PADDING + 'px';
}
contentEl.style.top = popoverCSS.top + 'px';
contentEl.style.left = popoverCSS.left + 'px';
contentEl.style.transformOrigin = originY + ' ' + originX;
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const contentAnimation = createAnimation();
const viewportAnimation = createAnimation();
const baseAnimation = new AnimationC();
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 0.32);
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation.fromTo('opacity', 0.01, 0.32);
wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper'))
.fromTo('opacity', 0.01, 1);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.popover-wrapper'));
wrapperAnimation.fromTo('opacity', 0.01, 1);
contentAnimation
.addElement(contentEl)
.beforeStyles({
'top': `${popoverCSS.top}px`,
'left': `${popoverCSS.left}px`,
'transform-origin': `${originY} ${originX}`
})
.fromTo('transform', 'scale(0.001)', 'scale(1)');
const contentAnimation = new AnimationC();
contentAnimation.addElement(baseEl.querySelector('.popover-content'));
contentAnimation.fromTo('scale', 0.001, 1);
viewportAnimation
.addElement(baseEl.querySelector('.popover-viewport'))
.fromTo('opacity', 0.01, 1);
const viewportAnimation = new AnimationC();
viewportAnimation.addElement(baseEl.querySelector('.popover-viewport'));
viewportAnimation.fromTo('opacity', 0.01, 1);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(300)
.add(backdropAnimation)
.add(wrapperAnimation)
.add(contentAnimation)
.add(viewportAnimation));
.addAnimation([backdropAnimation, wrapperAnimation, contentAnimation, viewportAnimation]);
};
const POPOVER_MD_BODY_PADDING = 12;

View File

@@ -1,24 +1,24 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* Md Popover Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: HTMLElement): Promise<Animation> => {
const baseAnimation = new AnimationC();
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const backdropAnimation = new AnimationC();
backdropAnimation.addElement(baseEl.querySelector('ion-backdrop'));
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.32, 0);
const wrapperAnimation = new AnimationC();
wrapperAnimation.addElement(baseEl.querySelector('.popover-wrapper'));
wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper'))
.fromTo('opacity', 0.99, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0);
backdropAnimation.fromTo('opacity', 0.32, 0);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(500)
.add(backdropAnimation)
.add(wrapperAnimation));
.addAnimation([backdropAnimation, wrapperAnimation]);
};

View File

@@ -1,24 +1,23 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Toast Enter Animation
*/
export const iosEnterAnimation = (AnimationC: Animation, baseEl: ShadowRoot, position: string): Promise<Animation> => {
const baseAnimation = new AnimationC();
const wrapperAnimation = new AnimationC();
export const iosEnterAnimation = (baseEl: ShadowRoot, position: string): Animation => {
const baseAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const hostEl = baseEl.host || baseEl;
const wrapperEl = baseEl.querySelector('.toast-wrapper') as HTMLElement;
wrapperAnimation.addElement(wrapperEl);
const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
wrapperAnimation.addElement(wrapperEl);
switch (position) {
case 'top':
wrapperAnimation.fromTo('translateY', '-100%', top);
wrapperAnimation.fromTo('transform', 'translateY(-100%)', `translateY(${top})`);
break;
case 'middle':
const topPosition = Math.floor(
@@ -28,12 +27,12 @@ export const iosEnterAnimation = (AnimationC: Animation, baseEl: ShadowRoot, pos
wrapperAnimation.fromTo('opacity', 0.01, 1);
break;
default:
wrapperAnimation.fromTo('translateY', '100%', bottom);
wrapperAnimation.fromTo('transform', 'translateY(100%)', `translateY(${bottom})`);
break;
}
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(hostEl)
.easing('cubic-bezier(.155,1.105,.295,1.12)')
.duration(400)
.add(wrapperAnimation));
.addAnimation(wrapperAnimation);
};

View File

@@ -1,35 +1,34 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* iOS Toast Leave Animation
*/
export const iosLeaveAnimation = (AnimationC: Animation, baseEl: ShadowRoot, position: string): Promise<Animation> => {
const baseAnimation = new AnimationC();
const wrapperAnimation = new AnimationC();
export const iosLeaveAnimation = (baseEl: ShadowRoot, position: string): Animation => {
const baseAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const hostEl = baseEl.host || baseEl;
const wrapperEl = baseEl.querySelector('.toast-wrapper') as HTMLElement;
wrapperAnimation.addElement(wrapperEl);
const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
wrapperAnimation.addElement(wrapperEl);
switch (position) {
case 'top':
wrapperAnimation.fromTo('translateY', top, '-100%');
wrapperAnimation.fromTo('transform', `translateY(${top})`, 'translateY(-100%)');
break;
case 'middle':
wrapperAnimation.fromTo('opacity', 0.99, 0);
break;
default:
wrapperAnimation.fromTo('translateY', bottom, '100%');
wrapperAnimation.fromTo('transform', `translateY(${bottom})`, 'translateY(100%)');
break;
}
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(hostEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(300)
.add(wrapperAnimation));
.addAnimation(wrapperAnimation);
};

View File

@@ -1,21 +1,20 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* MD Toast Enter Animation
*/
export const mdEnterAnimation = (AnimationC: Animation, baseEl: ShadowRoot, position: string): Promise<Animation> => {
const baseAnimation = new AnimationC();
const wrapperAnimation = new AnimationC();
export const mdEnterAnimation = (baseEl: ShadowRoot, position: string): Animation => {
const baseAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const hostEl = baseEl.host || baseEl;
const wrapperEl = baseEl.querySelector('.toast-wrapper') as HTMLElement;
wrapperAnimation.addElement(wrapperEl);
const bottom = `calc(8px + var(--ion-safe-area-bottom, 0px))`;
const top = `calc(8px + var(--ion-safe-area-top, 0px))`;
wrapperAnimation.addElement(wrapperEl);
switch (position) {
case 'top':
wrapperEl.style.top = top;
@@ -33,9 +32,9 @@ export const mdEnterAnimation = (AnimationC: Animation, baseEl: ShadowRoot, posi
wrapperAnimation.fromTo('opacity', 0.01, 1);
break;
}
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(hostEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(400)
.add(wrapperAnimation));
.addAnimation(wrapperAnimation);
};

View File

@@ -1,23 +1,22 @@
import { Animation } from '../../../interface';
import { Animation, createAnimation } from '../../../utils/animation/animation';
/**
* md Toast Leave Animation
*/
export const mdLeaveAnimation = (AnimationC: Animation, baseEl: ShadowRoot): Promise<Animation> => {
const baseAnimation = new AnimationC();
const wrapperAnimation = new AnimationC();
export const mdLeaveAnimation = (baseEl: ShadowRoot): Animation => {
const baseAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const hostEl = baseEl.host || baseEl;
const wrapperEl = baseEl.querySelector('.toast-wrapper') as HTMLElement;
wrapperAnimation.addElement(wrapperEl);
wrapperAnimation
.addElement(wrapperEl)
.fromTo('opacity', 0.99, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0);
return Promise.resolve(baseAnimation
return baseAnimation
.addElement(hostEl)
.easing('cubic-bezier(.36,.66,.04,1)')
.duration(300)
.add(wrapperAnimation));
.addAnimation(wrapperAnimation);
};

View File

@@ -1,5 +1,5 @@
import { config } from '../global/config';
import { ActionSheetOptions, AlertOptions, AnimationBuilder, BackButtonEvent, HTMLIonOverlayElement, IonicConfig, LoadingOptions, ModalOptions, OverlayInterface, PickerOptions, PopoverOptions, ToastOptions } from '../interface';
import { ActionSheetOptions, AlertOptions, BackButtonEvent, HTMLIonOverlayElement, IonicConfig, LoadingOptions, ModalOptions, OverlayInterface, PickerOptions, PopoverOptions, ToastOptions } from '../interface';
let lastId = 0;
@@ -111,8 +111,8 @@ export const getOverlay = (doc: Document, overlayTag?: string, id?: string): HTM
export const present = async (
overlay: OverlayInterface,
name: keyof IonicConfig,
iosEnterAnimation: AnimationBuilder,
mdEnterAnimation: AnimationBuilder,
iosEnterAnimation: any,
mdEnterAnimation: any,
opts?: any
) => {
if (overlay.presented) {
@@ -137,8 +137,8 @@ export const dismiss = async (
data: any | undefined,
role: string | undefined,
name: keyof IonicConfig,
iosLeaveAnimation: AnimationBuilder,
mdLeaveAnimation: AnimationBuilder,
iosLeaveAnimation: any,
mdLeaveAnimation: any,
opts?: any
): Promise<boolean> => {
if (!overlay.presented) {
@@ -170,12 +170,12 @@ const getAppRoot = (doc: Document) => {
const overlayAnimation = async (
overlay: OverlayInterface,
animationBuilder: AnimationBuilder,
animationBuilder: any,
baseEl: any,
opts: any
): Promise<boolean> => {
if (overlay.animation) {
overlay.animation.destroy();
// overlay.animation.destroy();
overlay.animation = undefined;
return false;
}
@@ -183,7 +183,9 @@ const overlayAnimation = async (
baseEl.classList.remove('overlay-hidden');
const aniRoot = baseEl.shadowRoot || overlay.el;
const animation = await import('./animation').then(mod => mod.create(animationBuilder, aniRoot, opts));
console.log(opts);
const animation = (['ActionSheet', 'Alert', 'Loading', 'Modal', 'Picker', 'Popover', 'Toast'].includes(overlay.constructor.name)) ? animationBuilder(aniRoot, opts) : await import('./animation').then(mod => mod.create(animationBuilder, aniRoot, opts));
overlay.animation = animation;
if (!overlay.animated || !config.getBoolean('animated', true)) {
animation.duration(0);
@@ -198,7 +200,7 @@ const overlayAnimation = async (
}
await animation.playAsync();
const hasCompleted = animation.hasCompleted;
animation.destroy();
// animation.destroy();
overlay.animation = undefined;
return hasCompleted;
};

View File

@@ -77,32 +77,30 @@ const animation = async (animationBuilder: AnimationBuilder, opts: TransitionOpt
await waitForReady(opts, true);
const trans = await import('../animation').then(mod => mod.create(animationBuilder, opts.baseEl, opts));
trans;
fireWillEvents(opts.enteringEl, opts.leavingEl);
const animation = ((opts.mode === 'ios')
const anim = ((opts.mode === 'ios')
? (await iosTransitionAnimation()).newIosTransitionAnimation(opts.baseEl, opts)
: (await mdTransitionAnimation()).newMdTransitionAnimation(opts) as any);
animation;
console.log(trans, anim);
await playTransition(animation, opts);
await playTransition(anim, opts);
animation.hasCompleted = true;
anim.hasCompleted = true;
if (opts.progressCallback) {
opts.progressCallback(undefined);
}
if (animation.hasCompleted) {
if (anim.hasCompleted) {
fireDidEvents(opts.enteringEl, opts.leavingEl);
}
console.log('done!');
return {
hasCompleted: animation.hasCompleted,
animation
hasCompleted: anim.hasCompleted,
animation: anim
};
};

View File

@@ -27,8 +27,8 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
const headerEls = enteringEl.querySelectorAll(':scope > ion-header > *:not(ion-toolbar), :scope > ion-footer > *');
const enteringToolBarEls = enteringEl.querySelectorAll(':scope > ion-header > ion-toolbar');
const rootAnimation = createAnimation('ios-root-animation');
const enteringContentAnimation = createAnimation('ios-entering-content-animation');
const rootAnimation = createAnimation();
const enteringContentAnimation = createAnimation();
rootAnimation
.addElement(enteringEl)
@@ -37,7 +37,7 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
.beforeRemoveClass('ion-page-invisible');
if (leavingEl && navEl) {
const navDecorAnimation = createAnimation('ios-decor-animation');
const navDecorAnimation = createAnimation();
navDecorAnimation.addElement(navEl);
rootAnimation.addAnimation(navDecorAnimation);
}
@@ -60,18 +60,18 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
// entering content, forward direction
enteringContentAnimation
.beforeClearStyles([OPACITY])
.fromTo('transform', `translateX(${OFF_RIGHT})`, `translateX(${CENTER})`);
.fromTo('transform', `translateX(${OFF_RIGHT})`, `translateX(${CENTER})`);
}
if (contentEl) {
const enteringTransitionEffectEl = shadow(contentEl).querySelector('.transition-effect');
if (enteringTransitionEffectEl) {
const enteringTransitionCoverEl = enteringTransitionEffectEl.querySelector('.transition-cover');
const enteringTransitionShadowEl = enteringTransitionEffectEl.querySelector('.transition-shadow');
const enteringTransitionEffect = createAnimation('ios-entering-transition-effect');
const enteringTransitionCover = createAnimation('ios-entering-transition-cover');
const enteringTransitionShadow = createAnimation('ios-entering-transition-shadow');
const enteringTransitionEffect = createAnimation();
const enteringTransitionCover = createAnimation();
const enteringTransitionShadow = createAnimation();
enteringTransitionEffect
.addElement(enteringTransitionEffectEl)
@@ -87,30 +87,30 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
.addElement(enteringTransitionShadowEl)
.beforeClearStyles([OPACITY])
.fromTo(OPACITY, 0.03, 0.70);
enteringTransitionEffect.addAnimation([enteringTransitionCover, enteringTransitionShadow]);
enteringContentAnimation.addAnimation([enteringTransitionEffect]);
}
}
enteringToolBarEls.forEach((enteringToolBarEl, i) => {
const enteringToolBar = createAnimation(`ios-entering-toolbar-${i}`);
enteringToolBarEls.forEach(enteringToolBarEl => {
const enteringToolBar = createAnimation();
enteringToolBar.addElement(enteringToolBarEl);
rootAnimation.addAnimation(enteringToolBar);
const enteringTitle = createAnimation(`ios-entering-toolbar-${i}-title`);
const enteringTitle = createAnimation();
enteringTitle.addElement(enteringToolBarEl.querySelector('ion-title'));
const enteringToolBarButtons = createAnimation(`ios-entering-toolbar-${i}-buttons`);
const enteringToolBarButtons = createAnimation();
enteringToolBarButtons.addElement(enteringToolBarEl.querySelectorAll('ion-buttons,[menuToggle]'));
const enteringToolBarItems = createAnimation(`ios-entering-toolbar-${i}-items`);
const enteringToolBarItems = createAnimation();
enteringToolBarItems.addElement(enteringToolBarEl.querySelectorAll(':scope > *:not(ion-title):not(ion-buttons):not([menuToggle])'));
const enteringToolBarBg = createAnimation(`ios-entering-toolbar-${i}-bg`);
const enteringToolBarBg = createAnimation();
enteringToolBarBg.addElement(shadow(enteringToolBarEl).querySelector('.toolbar-background'));
const enteringBackButton = createAnimation(`ios-entering-toolbar-${i}-back-button`);
const enteringBackButton = createAnimation();
const backButtonEl = enteringToolBarEl.querySelector('ion-back-button');
if (backButtonEl) {
@@ -143,7 +143,7 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
enteringBackButton.fromTo(OPACITY, 0.01, 1);
if (backButtonEl) {
const enteringBackBtnText = createAnimation(`ios-entering-toolbar-${i}-back-button-text`);
const enteringBackBtnText = createAnimation();
enteringBackBtnText
.addElement(shadow(backButtonEl).querySelector('.button-text'))
.fromTo(`transform`, (isRTL ? 'translateX(-100px)' : 'translateX(100px)'), 'translateX(0px)');
@@ -156,9 +156,9 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
// setup leaving view
if (leavingEl) {
let leavingContent = createAnimation(`ios-leaving-content-animation`);
const leavingContent = createAnimation();
const leavingContentEl = leavingEl.querySelector(':scope > ion-content');
leavingContent.addElement(leavingContentEl);
leavingContent.addElement(leavingEl.querySelectorAll(':scope > ion-header > *:not(ion-toolbar), :scope > ion-footer > *'));
rootAnimation.addAnimation(leavingContent);
@@ -175,7 +175,7 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
.fromTo('transform', `translateX(${CENTER})`, `translateX(${OFF_LEFT})`)
.fromTo(OPACITY, 1, OFF_OPACITY);
}
if (leavingContentEl) {
const leavingTransitionEffectEl = shadow(leavingContentEl).querySelector('.transition-effect');
@@ -183,9 +183,9 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
const leavingTransitionCoverEl = leavingTransitionEffectEl.querySelector('.transition-cover');
const leavingTransitionShadowEl = leavingTransitionEffectEl.querySelector('.transition-shadow');
const leavingTransitionEffect = createAnimation('ios-leaving-transition-effect');
const leavingTransitionCover = createAnimation('ios-leaving-transition-cover');
const leavingTransitionShadow = createAnimation('ios-leaving-transition-shadow');
const leavingTransitionEffect = createAnimation();
const leavingTransitionCover = createAnimation();
const leavingTransitionShadow = createAnimation();
leavingTransitionEffect
.addElement(leavingTransitionEffectEl)
@@ -201,33 +201,33 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
.addElement(leavingTransitionShadowEl)
.beforeClearStyles([OPACITY])
.fromTo(OPACITY, 0.70, 0.03);
leavingTransitionEffect.addAnimation([leavingTransitionCover, leavingTransitionShadow]);
leavingContent.addAnimation([leavingTransitionEffect]);
}
}
const leavingToolBarEls = leavingEl.querySelectorAll(':scope > ion-header > ion-toolbar');
leavingToolBarEls.forEach((leavingToolBarEl, i) => {
const leavingToolBar = createAnimation(`ios-leaving-toolbar-${i}-animation`);
leavingToolBarEls.forEach(leavingToolBarEl => {
const leavingToolBar = createAnimation();
leavingToolBar.addElement(leavingToolBarEl);
const leavingTitle = createAnimation(`ios-leaving-toolbar-${i}-title-animation`);
const leavingTitle = createAnimation();
leavingTitle.addElement(leavingToolBarEl.querySelector('ion-title'));
const leavingToolBarButtons = createAnimation(`ios-leaving-toolbar-${i}-buttons-animation`);
const leavingToolBarButtons = createAnimation();
leavingToolBarButtons.addElement(leavingToolBarEl.querySelectorAll('ion-buttons,[menuToggle]'));
const leavingToolBarItems = createAnimation(`ios-leaving-toolbar-${i}-items-animation`);
const leavingToolBarItems = createAnimation();
const leavingToolBarItemEls = leavingToolBarEl.querySelectorAll(':scope > *:not(ion-title):not(ion-buttons):not([menuToggle])');
if (leavingToolBarItemEls.length > 0) {
leavingToolBarItems.addElement(leavingToolBarItemEls);
}
const leavingToolBarBg = createAnimation(`ios-leaving-toolbar-${i}-bg-animation`);
const leavingToolBarBg = createAnimation();
leavingToolBarBg.addElement(shadow(leavingToolBarEl).querySelector('.toolbar-background'));
const leavingBackButton = createAnimation(`ios-leaving-toolbar-${i}-back-button-animation`);
const leavingBackButton = createAnimation();
const backButtonEl = leavingToolBarEl.querySelector('ion-back-button');
if (backButtonEl) {
leavingBackButton.addElement(backButtonEl);
@@ -254,7 +254,7 @@ export const newIosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOp
.fromTo(OPACITY, 1, 0.01);
if (backButtonEl) {
const leavingBackBtnText = createAnimation(`ios-leaving-toolbar-${i}-back-button-text`);
const leavingBackBtnText = createAnimation();
leavingBackBtnText.addElement(shadow(backButtonEl).querySelector('.button-text'));
leavingBackBtnText.fromTo('transform', `translateX(${CENTER})`, `translateX(${(isRTL ? -124 : 124) + 'px'})`);
leavingToolBar.addAnimation(leavingBackBtnText);

View File

@@ -7,7 +7,7 @@ export const newMdTransitionAnimation = (opts: TransitionOptions): AnimationNew
const OFF_BOTTOM = '40px';
const CENTER = '0px';
const rootAnimation = createAnimation('md-root-animation');
const rootAnimation = createAnimation();
const enteringEl = opts.enteringEl;
const leavingEl = opts.leavingEl;
@@ -34,7 +34,7 @@ export const newMdTransitionAnimation = (opts: TransitionOptions): AnimationNew
}
if (enteringToolbarEle) {
const enteringToolBarAnimation = createAnimation('md-entering-toolbar-animation');
const enteringToolBarAnimation = createAnimation();
enteringToolBarAnimation.addElement(enteringToolbarEle);
rootAnimation.addAnimation(enteringToolBarAnimation);
}
@@ -44,7 +44,7 @@ export const newMdTransitionAnimation = (opts: TransitionOptions): AnimationNew
.duration(opts.duration || 200)
.easing('cubic-bezier(0.47,0,0.745,0.715)');
const leavingPageAnimation = createAnimation('md-leaving-page-animation');
const leavingPageAnimation = createAnimation();
leavingPageAnimation
.addElement(getIonPageElement(leavingEl))
.fromTo('transform', `translateY(${CENTER})`, `translateY(${OFF_BOTTOM})`)