mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
10 Commits
cb/module-
...
motion
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede6289bc6 | ||
|
|
f077f0aac7 | ||
|
|
9c64308f0d | ||
|
|
795783311a | ||
|
|
f3e8d4c31d | ||
|
|
7fb38d1e12 | ||
|
|
9f9ba235ee | ||
|
|
28c5e14434 | ||
|
|
a4be67aeb8 | ||
|
|
94c3d481e9 |
@@ -250,7 +250,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
|||||||
onIonBackdropTap={this.onBackdropTap}
|
onIonBackdropTap={this.onBackdropTap}
|
||||||
>
|
>
|
||||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||||
<div class="action-sheet-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
|
<div class="action-sheet-wrapper ion-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
|
||||||
<div class="action-sheet-container">
|
<div class="action-sheet-container">
|
||||||
<div class="action-sheet-group" ref={el => this.groupEl = el}>
|
<div class="action-sheet-group" ref={el => this.groupEl = el}>
|
||||||
{this.header !== undefined &&
|
{this.header !== undefined &&
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
|||||||
|
|
||||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||||
|
|
||||||
<div class="alert-wrapper" ref={el => this.wrapperEl = el}>
|
<div class="alert-wrapper ion-wrapper" ref={el => this.wrapperEl = el}>
|
||||||
|
|
||||||
<div class="alert-head">
|
<div class="alert-head">
|
||||||
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
|
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class Loading implements ComponentInterface, OverlayInterface {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss} />
|
<ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss} />
|
||||||
<div class="loading-wrapper" role="dialog">
|
<div class="loading-wrapper ion-wrapper" role="dialog">
|
||||||
{spinner && (
|
{spinner && (
|
||||||
<div class="loading-spinner">
|
<div class="loading-spinner">
|
||||||
<ion-spinner name={spinner} aria-hidden="true" />
|
<ion-spinner name={spinner} aria-hidden="true" />
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
{mode === 'ios' && <div class="modal-shadow"></div>}
|
{mode === 'ios' && <div class="modal-shadow"></div>}
|
||||||
<div
|
<div
|
||||||
role="dialog"
|
role="dialog"
|
||||||
class="modal-wrapper"
|
class="modal-wrapper ion-wrapper"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</Host>
|
</Host>
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
|||||||
tappable={this.backdropDismiss}
|
tappable={this.backdropDismiss}
|
||||||
>
|
>
|
||||||
</ion-backdrop>
|
</ion-backdrop>
|
||||||
<div class="picker-wrapper" role="dialog">
|
<div class="picker-wrapper ion-wrapper" role="dialog">
|
||||||
<div class="picker-toolbar">
|
<div class="picker-toolbar">
|
||||||
{this.buttons.map(b => (
|
{this.buttons.map(b => (
|
||||||
<div class={buttonWrapperClass(b)}>
|
<div class={buttonWrapperClass(b)}>
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
|||||||
onIonBackdropTap={this.onBackdropTap}
|
onIonBackdropTap={this.onBackdropTap}
|
||||||
>
|
>
|
||||||
<ion-backdrop tappable={this.backdropDismiss} visible={this.showBackdrop}/>
|
<ion-backdrop tappable={this.backdropDismiss} visible={this.showBackdrop}/>
|
||||||
<div class="popover-wrapper">
|
<div class="popover-wrapper ion-wrapper">
|
||||||
<div class="popover-arrow"></div>
|
<div class="popover-arrow"></div>
|
||||||
<div class="popover-content"></div>
|
<div class="popover-content"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ export class Toast implements ComponentInterface, OverlayInterface {
|
|||||||
const mode = getIonMode(this);
|
const mode = getIonMode(this);
|
||||||
const wrapperClass = {
|
const wrapperClass = {
|
||||||
'toast-wrapper': true,
|
'toast-wrapper': true,
|
||||||
|
'ion-wrapper': true,
|
||||||
[`toast-${this.position}`]: true
|
[`toast-${this.position}`]: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
34
packages/motion/.eslintrc.js
Normal file
34
packages/motion/.eslintrc.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
project: './tsconfig.json',
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: ['@ionic'],
|
||||||
|
extends: ['plugin:@ionic/strict'],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-explicit-any": 0,
|
||||||
|
"no-negated-condition": 0,
|
||||||
|
"no-conditional-assignment": 0,
|
||||||
|
"no-non-null-assertion": 0,
|
||||||
|
"no-unnecessary-type-assertion": 0,
|
||||||
|
"no-import-side-effect": 0,
|
||||||
|
"trailing-comma": 0,
|
||||||
|
"no-null-keyword": 0,
|
||||||
|
"no-console": 0,
|
||||||
|
"no-floating-promises": 0,
|
||||||
|
|
||||||
|
"jsx-key": 0,
|
||||||
|
"jsx-self-close": 0,
|
||||||
|
"jsx-no-bind": 0,
|
||||||
|
"jsx-no-lambda": 0,
|
||||||
|
"jsx-no-multiline-js": 0,
|
||||||
|
"jsx-wrap-multiline": 0
|
||||||
|
}
|
||||||
|
};
|
||||||
1
packages/motion/.npmrc
Normal file
1
packages/motion/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package-lock=false
|
||||||
46
packages/motion/package.json
Normal file
46
packages/motion/package.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@ionic/motion",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Motion animations for Ionic Framework",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm -rf dist",
|
||||||
|
"build": "npm run clean && tsc -p . && cp package.json ./dist/package.json",
|
||||||
|
"lint": "eslint src/**/*",
|
||||||
|
"lint.fix": "npm run lint -- --fix"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ionic-team/ionic.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"ionic",
|
||||||
|
"framework",
|
||||||
|
"react",
|
||||||
|
"angular",
|
||||||
|
"mobile",
|
||||||
|
"app",
|
||||||
|
"hybrid",
|
||||||
|
"webapp",
|
||||||
|
"cordova",
|
||||||
|
"capacitor",
|
||||||
|
"progressive",
|
||||||
|
"web",
|
||||||
|
"app",
|
||||||
|
"pwa"
|
||||||
|
],
|
||||||
|
"author": "Ionic Team",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ionic-team/ionic/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://ionicframework.com/",
|
||||||
|
"devDependencies": {
|
||||||
|
"@ionic/eslint-plugin": "0.0.1",
|
||||||
|
"@typescript-eslint/parser": "^2.33.0",
|
||||||
|
"eslint": "^7.0.0",
|
||||||
|
"typescript": "^3.9.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ionic/core": "^5.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/motion/readme.md
Normal file
1
packages/motion/readme.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# @ionic/motion
|
||||||
175
packages/motion/src/animations/axis.motion.ts
Normal file
175
packages/motion/src/animations/axis.motion.ts
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
import { Animation, AnimationBuilder, createAnimation } from '@ionic/core';
|
||||||
|
import { AnimationOptions, Axis } from '../';
|
||||||
|
|
||||||
|
const createXAxisTransition = (enteringEl: HTMLElement, leavingEl: HTMLElement, backDirection: boolean): Animation[] => {
|
||||||
|
const enteringTransition = createAnimation().addElement(enteringEl);
|
||||||
|
const leavingTransition = createAnimation().addElement(leavingEl);
|
||||||
|
|
||||||
|
if (backDirection) {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'translate3d(-30px, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'translate3d(30px, 0, 0)' },
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'translate3d(30px, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'translate3d(-30px, 0, 0)' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [enteringTransition, leavingTransition];
|
||||||
|
};
|
||||||
|
const createYAxisTransition = (enteringEl: HTMLElement, leavingEl: HTMLElement, backDirection: boolean): Animation[] => {
|
||||||
|
const enteringTransition = createAnimation().addElement(enteringEl);
|
||||||
|
const leavingTransition = createAnimation().addElement(leavingEl);
|
||||||
|
|
||||||
|
if (backDirection) {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'translate3d(0, -30px, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'translate3d(0, 30px, 0)' },
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'translate3d(0, 30px, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'translate3d(0, -30px, 0)' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [enteringTransition, leavingTransition];
|
||||||
|
};
|
||||||
|
const createFadeZAxisTransition = (enteringEl: HTMLElement, leavingEl: HTMLElement, backDirection: boolean): Animation[] => {
|
||||||
|
const enteringTransition = createAnimation().addElement(enteringEl);
|
||||||
|
const leavingTransition = createAnimation().addElement(leavingEl);
|
||||||
|
|
||||||
|
if (backDirection) {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale3d(1.1, 1.1, 1)' },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
{ offset: 0.2, opacity: 1 },
|
||||||
|
{ offset: 0.4, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'scale3d(0.8, 0.8, 1)' },
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale3d(0.8, 0.8, 1)' },
|
||||||
|
{ offset: 0.2, opacity: 0 },
|
||||||
|
{ offset: 0.4, opacity: 1 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
{ offset: 1, transform: 'scale3d(1.1, 1.1, 1)' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [enteringTransition, leavingTransition];
|
||||||
|
};
|
||||||
|
const createNormalZAxisTransition = (enteringEl: HTMLElement, leavingEl: HTMLElement, backDirection: boolean): Animation[] => {
|
||||||
|
const enteringTransition = createAnimation().addElement(enteringEl);
|
||||||
|
const leavingTransition = createAnimation().addElement(leavingEl);
|
||||||
|
|
||||||
|
if (backDirection) {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale3d(1.1, 1.1, 1)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'scale3d(0.8, 0.8, 1)' },
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
enteringTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale3d(0.8, 0.8, 1)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
leavingTransition
|
||||||
|
.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'scale3d(1, 1, 1)' },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'scale3d(1.1, 1.1, 1)' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [enteringTransition, leavingTransition];
|
||||||
|
};
|
||||||
|
const createZAxisTransition = (enteringEl: HTMLElement, leavingEl: HTMLElement, fade: boolean, backDirection: boolean): Animation[] => fade ? createFadeZAxisTransition(enteringEl, leavingEl, backDirection) : createNormalZAxisTransition(enteringEl, leavingEl, backDirection);
|
||||||
|
|
||||||
|
export const sharedAxisTransition = (axis: Axis = 'z', fade: boolean = false, animationOpts: AnimationOptions = {}): AnimationBuilder => {
|
||||||
|
const { duration, easing } = animationOpts;
|
||||||
|
|
||||||
|
return (_: HTMLElement, opts: any): Animation => {
|
||||||
|
const backDirection = opts.direction === 'back';
|
||||||
|
const { enteringEl, leavingEl } = opts;
|
||||||
|
|
||||||
|
const baseTransition = createAnimation()
|
||||||
|
.duration(duration !== undefined ? duration : 300)
|
||||||
|
.easing(easing || 'ease');
|
||||||
|
|
||||||
|
switch (axis) {
|
||||||
|
case 'x':
|
||||||
|
baseTransition.addAnimation(createXAxisTransition(enteringEl, leavingEl, backDirection));
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
baseTransition.addAnimation(createYAxisTransition(enteringEl, leavingEl, backDirection));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
baseTransition.addAnimation(createZAxisTransition(enteringEl, leavingEl, fade, backDirection));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseTransition;
|
||||||
|
};
|
||||||
|
};
|
||||||
63
packages/motion/src/animations/fade-through.motion.ts
Normal file
63
packages/motion/src/animations/fade-through.motion.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { AnimationOptions } from '../';
|
||||||
|
import { Animation, AnimationBuilder, createAnimation } from '@ionic/core';
|
||||||
|
|
||||||
|
const createBase = (animationOpts: AnimationOptions, enteringEl: HTMLElement, leavingEl: HTMLElement): { [key: string]: Animation; } => {
|
||||||
|
const { duration, easing } = animationOpts;
|
||||||
|
const rootAnimation = createAnimation()
|
||||||
|
.duration(duration !== undefined ? duration : 300)
|
||||||
|
.easing(easing || 'ease');
|
||||||
|
|
||||||
|
const leavingAnimation = createAnimation().addElement(leavingEl);
|
||||||
|
const enteringAnimation = createAnimation().addElement(enteringEl);
|
||||||
|
|
||||||
|
rootAnimation.addAnimation([leavingAnimation, enteringAnimation]);
|
||||||
|
|
||||||
|
return { rootAnimation, enteringAnimation, leavingAnimation };
|
||||||
|
};
|
||||||
|
|
||||||
|
const enter = (animationOpts: AnimationOptions, enteringEl: HTMLElement, leavingEl: HTMLElement): Animation => {
|
||||||
|
const { rootAnimation, enteringAnimation, leavingAnimation } = createBase(animationOpts, enteringEl, leavingEl);
|
||||||
|
|
||||||
|
leavingAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 1 },
|
||||||
|
{ offset: 0.3, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 0 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
enteringAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale(0.92)' },
|
||||||
|
{ offset: 0.3, opacity: 0, transform: 'scale(0.92)' },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale(1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
return rootAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const leave = (animationOpts: AnimationOptions, enteringEl: HTMLElement, leavingEl: HTMLElement): Animation => {
|
||||||
|
const { rootAnimation, enteringAnimation, leavingAnimation } = createBase(animationOpts, enteringEl, leavingEl);
|
||||||
|
|
||||||
|
leavingAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 1, transform: 'scale(1)' },
|
||||||
|
{ offset: 0.7, opacity: 0, transform: 'scale(0.92)' },
|
||||||
|
{ offset: 1, opacity: 0, transform: 'scale(0.92)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
enteringAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 0 },
|
||||||
|
{ offset: 0.7, opacity: 0 },
|
||||||
|
{ offset: 1, opacity: 1 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
return rootAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fadeThroughMotionEnter = (presentingEl: HTMLElement, animationOpts: AnimationOptions = {}): AnimationBuilder => (baseEl: HTMLElement): Animation => enter(animationOpts, baseEl, presentingEl);
|
||||||
|
|
||||||
|
export const fadeThroughMotionLeave = (presentingEl: HTMLElement, animationOpts: AnimationOptions = {}): AnimationBuilder => (baseEl: HTMLElement): Animation => leave(animationOpts, presentingEl, baseEl);
|
||||||
|
|
||||||
|
export const fadeThroughMotion = (animationOpts: AnimationOptions = {}): AnimationBuilder => (_: HTMLElement, opts: any): Animation => {
|
||||||
|
const backDirection = opts.direction === 'back';
|
||||||
|
const { enteringEl, leavingEl } = opts;
|
||||||
|
|
||||||
|
return backDirection ? leave(animationOpts, enteringEl, leavingEl) : enter(animationOpts, enteringEl, leavingEl);
|
||||||
|
};
|
||||||
72
packages/motion/src/animations/fade.motion.ts
Normal file
72
packages/motion/src/animations/fade.motion.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { AnimationOptions } from '../';
|
||||||
|
import { getElementRoot } from '../utils';
|
||||||
|
import { Animation, AnimationBuilder, createAnimation } from '@ionic/core';
|
||||||
|
|
||||||
|
const createBase = (animationOpts: AnimationOptions, enteringEl: HTMLElement): { [key: string]: Animation; } => {
|
||||||
|
const { duration, easing } = animationOpts;
|
||||||
|
const rootAnimation = createAnimation()
|
||||||
|
.duration(duration !== undefined ? duration : 150)
|
||||||
|
.easing(easing || 'ease');
|
||||||
|
|
||||||
|
const elementAnimation = createAnimation().addElement(enteringEl);
|
||||||
|
|
||||||
|
rootAnimation.addAnimation([elementAnimation]);
|
||||||
|
|
||||||
|
return { rootAnimation, elementAnimation };
|
||||||
|
};
|
||||||
|
|
||||||
|
const enter = (animationOpts: AnimationOptions, baseEl: HTMLElement): Animation => {
|
||||||
|
const root = getElementRoot(baseEl);
|
||||||
|
const wrapper = (root.querySelector('.ion-wrapper') || baseEl) as HTMLElement;
|
||||||
|
const backdrop = root.querySelector('ion-backdrop');
|
||||||
|
const { rootAnimation, elementAnimation } = createBase(animationOpts, wrapper);
|
||||||
|
|
||||||
|
elementAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 0, transform: 'scale(0.8)' },
|
||||||
|
{ offset: 0.3, opacity: 1 },
|
||||||
|
{ offset: 1, opacity: 1, transform: 'scale(1)' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (backdrop) {
|
||||||
|
const backdropAnimation = createAnimation()
|
||||||
|
.addElement(backdrop)
|
||||||
|
.fromTo('opacity', '0', 'var(--backdrop-opacity, 1)');
|
||||||
|
|
||||||
|
rootAnimation.addAnimation(backdropAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const leave = (animationOpts: AnimationOptions, baseEl: HTMLElement): Animation => {
|
||||||
|
const root = getElementRoot(baseEl);
|
||||||
|
const wrapper = (root.querySelector('.ion-wrapper') || baseEl) as HTMLElement;
|
||||||
|
const backdrop = root.querySelector('ion-backdrop');
|
||||||
|
const { rootAnimation, elementAnimation } = createBase(animationOpts, wrapper);
|
||||||
|
|
||||||
|
elementAnimation.keyframes([
|
||||||
|
{ offset: 0, opacity: 1 },
|
||||||
|
{ offset: 1, opacity: 0 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (backdrop) {
|
||||||
|
const backdropAnimation = createAnimation()
|
||||||
|
.addElement(backdrop)
|
||||||
|
.fromTo('opacity', 'var(--backdrop-opacity, 1)', '0');
|
||||||
|
|
||||||
|
rootAnimation.addAnimation(backdropAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fadeMotionEnter = (animationOpts: AnimationOptions = {}): AnimationBuilder => (baseEl: HTMLElement): Animation => enter(animationOpts, baseEl);
|
||||||
|
|
||||||
|
export const fadeMotionLeave = (animationOpts: AnimationOptions = {}): AnimationBuilder => (baseEl: HTMLElement): Animation => leave(animationOpts, baseEl);
|
||||||
|
|
||||||
|
export const fadeMotion = (animationOpts: AnimationOptions = {}): AnimationBuilder => (_: HTMLElement, opts: any): Animation => {
|
||||||
|
const backDirection = opts.direction === 'back';
|
||||||
|
const { enteringEl, leavingEl } = opts;
|
||||||
|
|
||||||
|
return backDirection ? leave(animationOpts, leavingEl) : enter(animationOpts, enteringEl);
|
||||||
|
};
|
||||||
10
packages/motion/src/index.ts
Normal file
10
packages/motion/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export { sharedAxisTransition } from './animations/axis.motion';
|
||||||
|
export { fadeMotion, fadeMotionEnter, fadeMotionLeave } from './animations/fade.motion';
|
||||||
|
export { fadeThroughMotion, fadeThroughMotionEnter, fadeThroughMotionLeave } from './animations/fade-through.motion';
|
||||||
|
|
||||||
|
export interface AnimationOptions {
|
||||||
|
duration?: number;
|
||||||
|
easing?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Axis = 'x' | 'y' | 'z';
|
||||||
1
packages/motion/src/utils.ts
Normal file
1
packages/motion/src/utils.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const getElementRoot = (el: HTMLElement, fallback: HTMLElement = el) => el.shadowRoot || fallback;
|
||||||
35
packages/motion/tsconfig.json
Normal file
35
packages/motion/tsconfig.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"allowUnreachableCode": false,
|
||||||
|
"declaration": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"assumeChangesOnlyAffectDirectDependencies": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "h",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2017"
|
||||||
|
],
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"pretty": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"target": "es2017"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src",
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"**/test"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user