mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 05:21:52 +08:00
fix(animation): improve menu and go back swipe
This commit is contained in:
@ -13,6 +13,7 @@ export class Animation {
|
||||
private _fx: EffectProperty[];
|
||||
private _dur: number = null;
|
||||
private _es: string = null;
|
||||
private _rvEs: string = null;
|
||||
private _bfSty: { [property: string]: any; };
|
||||
private _bfAdd: string[];
|
||||
private _bfRm: string[];
|
||||
@ -114,6 +115,9 @@ export class Animation {
|
||||
* not have an easing, then it'll get the easing from its parent.
|
||||
*/
|
||||
getEasing(): string {
|
||||
if (this._rv && this._rvEs) {
|
||||
return this._rvEs;
|
||||
}
|
||||
return this._es !== null ? this._es : (this.parent && this.parent.getEasing()) || null;
|
||||
}
|
||||
|
||||
@ -125,6 +129,14 @@ export class Animation {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the easing for this reversed animation.
|
||||
*/
|
||||
easingReverse(name: string): Animation {
|
||||
this._rvEs = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "from" value for a specific property.
|
||||
*/
|
||||
@ -996,14 +1008,15 @@ export class Animation {
|
||||
/**
|
||||
* End the progress animation.
|
||||
*/
|
||||
progressEnd(shouldComplete: boolean, currentStepValue: number, maxDelta: number = 0) {
|
||||
progressEnd(shouldComplete: boolean, currentStepValue: number, dur: number = -1) {
|
||||
console.debug('Animation, progressEnd, shouldComplete', shouldComplete, 'currentStepValue', currentStepValue);
|
||||
|
||||
this._isAsync = (currentStepValue > 0.05 && currentStepValue < 0.95);
|
||||
|
||||
const stepValue = shouldComplete ? 1 : 0;
|
||||
const factor = Math.max(Math.abs(currentStepValue - stepValue), 0.5) * 2;
|
||||
const dur = 64 + factor * maxDelta;
|
||||
|
||||
if (dur < 0) {
|
||||
dur = this._dur;
|
||||
}
|
||||
this._isAsync = (currentStepValue > 0.05 && currentStepValue < 0.95 && dur > 30);
|
||||
|
||||
this._progressEnd(shouldComplete, stepValue, dur, this._isAsync);
|
||||
|
||||
|
@ -78,7 +78,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
'shouldCompleteRight', shouldCompleteRight,
|
||||
'currentStepValue', currentStepValue);
|
||||
|
||||
this.menu.swipeEnd(shouldCompleteLeft, shouldCompleteRight, currentStepValue);
|
||||
this.menu.swipeEnd(shouldCompleteLeft, shouldCompleteRight, currentStepValue, velocity);
|
||||
}
|
||||
|
||||
getElementStartPos(slide: SlideData, ev: any) {
|
||||
|
@ -15,10 +15,18 @@ export class MenuType {
|
||||
ani: Animation = new Animation();
|
||||
isOpening: boolean;
|
||||
|
||||
constructor() {
|
||||
this.ani
|
||||
.easing('cubic-bezier(0.0, 0.0, 0.2, 1)')
|
||||
.easingReverse('cubic-bezier(0.4, 0.0, 0.6, 1)')
|
||||
.duration(280);
|
||||
}
|
||||
|
||||
setOpen(shouldOpen: boolean, animated: boolean, done: Function) {
|
||||
let ani = this.ani
|
||||
.onFinish(done, true)
|
||||
.reverse(!shouldOpen);
|
||||
|
||||
if (animated) {
|
||||
ani.play();
|
||||
} else {
|
||||
@ -40,7 +48,7 @@ export class MenuType {
|
||||
this.ani.progressStep(stepValue);
|
||||
}
|
||||
|
||||
setProgressEnd(shouldComplete: boolean, currentStepValue: number, done: Function) {
|
||||
setProgressEnd(shouldComplete: boolean, currentStepValue: number, velocity: number, done: Function) {
|
||||
let isOpen = (this.isOpening && shouldComplete);
|
||||
if (!this.isOpening && !shouldComplete) {
|
||||
isOpen = true;
|
||||
@ -51,7 +59,9 @@ export class MenuType {
|
||||
done(isOpen);
|
||||
}, true);
|
||||
|
||||
this.ani.progressEnd(shouldComplete, currentStepValue);
|
||||
let dur = this.ani.getDuration() / (Math.abs(velocity) + 1);
|
||||
|
||||
this.ani.progressEnd(shouldComplete, currentStepValue, dur);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
@ -72,11 +82,6 @@ class MenuRevealType extends MenuType {
|
||||
super();
|
||||
|
||||
let openedX = (menu.width() * (menu.side === 'right' ? -1 : 1)) + 'px';
|
||||
|
||||
this.ani
|
||||
.easing('ease')
|
||||
.duration(250);
|
||||
|
||||
let contentOpen = new Animation(menu.getContentElement());
|
||||
contentOpen.fromTo('translateX', '0px', openedX);
|
||||
this.ani.add(contentOpen);
|
||||
@ -95,10 +100,6 @@ class MenuPushType extends MenuType {
|
||||
constructor(menu: Menu, platform: Platform) {
|
||||
super();
|
||||
|
||||
this.ani
|
||||
.easing('ease')
|
||||
.duration(250);
|
||||
|
||||
let contentOpenedX: string, menuClosedX: string, menuOpenedX: string;
|
||||
|
||||
if (menu.side === 'right') {
|
||||
@ -135,10 +136,6 @@ class MenuOverlayType extends MenuType {
|
||||
constructor(menu: Menu, platform: Platform) {
|
||||
super();
|
||||
|
||||
this.ani
|
||||
.easing('ease')
|
||||
.duration(250);
|
||||
|
||||
let closedX: string, openedX: string;
|
||||
if (menu.side === 'right') {
|
||||
// right side
|
||||
|
@ -58,6 +58,12 @@ ion-menu ion-backdrop {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.menu-content-open {
|
||||
cursor: pointer;
|
||||
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.menu-content-open ion-pane,
|
||||
.menu-content-open ion-content,
|
||||
.menu-content-open .toolbar {
|
||||
|
@ -465,7 +465,7 @@ export class Menu {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
swipeEnd(shouldCompleteLeft: boolean, shouldCompleteRight: boolean, stepValue: number) {
|
||||
swipeEnd(shouldCompleteLeft: boolean, shouldCompleteRight: boolean, stepValue: number, velocity: number) {
|
||||
if (!this._isAnimating) {
|
||||
return;
|
||||
}
|
||||
@ -478,7 +478,7 @@ export class Menu {
|
||||
shouldComplete = (this.side === 'right') ? shouldCompleteRight : shouldCompleteLeft;
|
||||
}
|
||||
|
||||
this._getType().setProgressEnd(shouldComplete, stepValue, (isOpen: boolean) => {
|
||||
this._getType().setProgressEnd(shouldComplete, stepValue, velocity, (isOpen: boolean) => {
|
||||
console.debug('menu, swipeEnd', this.side);
|
||||
this._after(isOpen);
|
||||
});
|
||||
@ -512,14 +512,9 @@ export class Menu {
|
||||
|
||||
this._cntEle.classList.add('menu-content-open');
|
||||
let callback = this.onBackdropClick.bind(this);
|
||||
this._events.pointerEvents({
|
||||
element: this._cntEle,
|
||||
pointerDown: callback
|
||||
});
|
||||
this._events.pointerEvents({
|
||||
element: this.backdrop.getNativeElement(),
|
||||
pointerDown: callback
|
||||
});
|
||||
this._events.listen(this._cntEle, 'click', callback, true);
|
||||
this._events.listen(this.backdrop.getNativeElement(), 'click', callback, true);
|
||||
|
||||
this.ionOpen.emit(true);
|
||||
|
||||
} else {
|
||||
|
@ -65,7 +65,7 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
super(config, elementRef, renderer);
|
||||
|
||||
this._sbEnabled = config.getBoolean('swipeBackEnabled');
|
||||
this._sbThreshold = config.getNumber('swipeBackThreshold', 40);
|
||||
this._sbThreshold = config.getNumber('swipeBackThreshold', 0);
|
||||
|
||||
this.id = 'n' + (++ctrlIds);
|
||||
}
|
||||
@ -918,10 +918,11 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
}
|
||||
}
|
||||
|
||||
swipeBackEnd(shouldComplete: boolean, currentStepValue: number) {
|
||||
swipeBackEnd(shouldComplete: boolean, currentStepValue: number, velocity: number) {
|
||||
if (this._sbTrns && this._sbGesture) {
|
||||
// the swipe back gesture has ended
|
||||
this._sbTrns.progressEnd(shouldComplete, currentStepValue, 300);
|
||||
const dur = this._sbTrns.getDuration() / (Math.abs(velocity) + 1);
|
||||
this._sbTrns.progressEnd(shouldComplete, currentStepValue, dur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,12 +53,13 @@ export class SwipeBackGesture extends SlideEdgeGesture {
|
||||
}
|
||||
|
||||
onSlideEnd(slide: SlideData, ev: any) {
|
||||
const velocity = slide.velocity;
|
||||
const currentStepValue = (slide.distance / slide.max);
|
||||
const isResetDirecction = slide.velocity < 0;
|
||||
const isResetDirecction = velocity < 0;
|
||||
const isMovingFast = Math.abs(slide.velocity) > 0.4;
|
||||
const isInResetZone = Math.abs(slide.delta) < Math.abs(slide.max) * 0.5;
|
||||
const shouldComplete = !swipeShouldReset(isResetDirecction, isMovingFast, isInResetZone);
|
||||
|
||||
this._nav.swipeBackEnd(shouldComplete, currentStepValue);
|
||||
this._nav.swipeBackEnd(shouldComplete, currentStepValue, velocity);
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,6 @@ export const PLATFORM_CONFIGS: {[key: string]: PlatformConfig} = {
|
||||
scrollAssist: isIOS,
|
||||
statusbarPadding: isCordova,
|
||||
swipeBackEnabled: isIOS,
|
||||
swipeBackThreshold: 40,
|
||||
tapPolyfill: isIOSUI,
|
||||
virtualScrollEventAssist: isIOSUI,
|
||||
disableScrollAssist: isIOS,
|
||||
|
Reference in New Issue
Block a user