fix(modal): sheet animation works correctly if breakpoints value does not include 1 (#23927)

This commit is contained in:
Liam DeBeasi
2021-09-14 15:27:59 -04:00
committed by GitHub
parent 497537ac73
commit 414f24685c
6 changed files with 14 additions and 12 deletions

View File

@ -26,15 +26,14 @@ export const createSheetEnterAnimation = (opts: ModalAnimationOptions) => {
} }
export const createSheetLeaveAnimation = (opts: ModalAnimationOptions) => { export const createSheetLeaveAnimation = (opts: ModalAnimationOptions) => {
const { currentBreakpoint, backdropBreakpoint, sortedBreakpoints } = opts; const { currentBreakpoint, backdropBreakpoint } = opts;
/** /**
* Backdrop does not always fade in from 0 to 1 if backdropBreakpoint * Backdrop does not always fade in from 0 to 1 if backdropBreakpoint
* is defined, so we need to account for that offset by figuring out * is defined, so we need to account for that offset by figuring out
* what the current backdrop value should be. * what the current backdrop value should be.
*/ */
const maxBreakpoint = sortedBreakpoints![sortedBreakpoints.length - 1]; const backdropValue = `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(currentBreakpoint!, backdropBreakpoint!)})`;
const backdropValue = `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(currentBreakpoint!, maxBreakpoint, backdropBreakpoint!)})`;
const defaultBackdrop = [ const defaultBackdrop = [
{ offset: 0, opacity: backdropValue }, { offset: 0, opacity: backdropValue },
{ offset: 1, opacity: 0 } { offset: 1, opacity: 0 }

View File

@ -130,8 +130,8 @@ export const createSheetGesture = (
]); ]);
backdropAnimation.keyframes([ backdropAnimation.keyframes([
{ offset: 0, opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(1 - offset, maxBreakpoint, backdropBreakpoint)})` }, { offset: 0, opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(1 - offset, backdropBreakpoint)})` },
{ offset: 1, opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(closest, maxBreakpoint, backdropBreakpoint)})` } { offset: 1, opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(closest, backdropBreakpoint)})` }
]); ]);
animation.progressStep(0); animation.progressStep(0);

View File

@ -28,5 +28,4 @@ export interface ModalAnimationOptions {
presentingEl?: HTMLElement; presentingEl?: HTMLElement;
currentBreakpoint?: number; currentBreakpoint?: number;
backdropBreakpoint?: number; backdropBreakpoint?: number;
sortedBreakpoints: number[];
} }

View File

@ -44,7 +44,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
private currentBreakpoint?: number; private currentBreakpoint?: number;
private wrapperEl?: HTMLElement; private wrapperEl?: HTMLElement;
private backdropEl?: HTMLIonBackdropElement; private backdropEl?: HTMLIonBackdropElement;
private sortedBreakpoints: number[] = [];
private inline = false; private inline = false;
private workingDelegate?: FrameworkDelegate; private workingDelegate?: FrameworkDelegate;
@ -421,7 +420,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
ani.progressStart(true, 1); ani.progressStart(true, 1);
const sortedBreakpoints = this.sortedBreakpoints = (this.breakpoints?.sort((a, b) => a - b)) || []; const sortedBreakpoints = (this.breakpoints?.sort((a, b) => a - b)) || [];
this.gesture = createSheetGesture( this.gesture = createSheetGesture(
this.el, this.el,
@ -481,7 +480,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
const enteringAnimation = activeAnimations.get(this) || []; const enteringAnimation = activeAnimations.get(this) || [];
this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, { presentingEl: this.presentingElement, currentBreakpoint: this.currentBreakpoint || this.initialBreakpoint, sortedBreakpoints: this.sortedBreakpoints, backdropBreakpoint: this.backdropBreakpoint }); this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, { presentingEl: this.presentingElement, currentBreakpoint: this.currentBreakpoint || this.initialBreakpoint, backdropBreakpoint: this.backdropBreakpoint });
const dismissed = await this.currentTransition; const dismissed = await this.currentTransition;

View File

@ -87,6 +87,7 @@
<ion-content class="ion-padding"> <ion-content class="ion-padding">
<ion-button id="sheet-modal" onclick="presentModal()">Present Sheet Modal</ion-button> <ion-button id="sheet-modal" onclick="presentModal()">Present Sheet Modal</ion-button>
<ion-button id="custom-breakpoint-modal" onclick="presentModal({ initialBreakpoint: 0.5, breakpoints: [0, 0.5, 1] })">Present Sheet Modal (Custom Breakpoints)</ion-button> <ion-button id="custom-breakpoint-modal" onclick="presentModal({ initialBreakpoint: 0.5, breakpoints: [0, 0.5, 1] })">Present Sheet Modal (Custom Breakpoints)</ion-button>
<ion-button id="custom-breakpoint-modal" onclick="presentModal({ initialBreakpoint: 0.5, breakpoints: [0, 0.5, 0.75] })">Present Sheet Modal (Max breakpoint is not 1)</ion-button>
<ion-button id="custom-backdrop-modal" onclick="presentModal({ backdropBreakpoint: 0.5 })">Present Sheet Modal (Custom Backdrop Breakpoint)</ion-button> <ion-button id="custom-backdrop-modal" onclick="presentModal({ backdropBreakpoint: 0.5 })">Present Sheet Modal (Custom Backdrop Breakpoint)</ion-button>
<ion-button id="custom-height-modal" onclick="presentModal({ cssClass: 'custom-height' })">Present Sheet Modal (Custom Height)</ion-button> <ion-button id="custom-height-modal" onclick="presentModal({ cssClass: 'custom-height' })">Present Sheet Modal (Custom Height)</ion-button>
<ion-button id="custom-handle-modal" onclick="presentModal({ cssClass: 'custom-handle' })">Present Sheet Modal (Custom Handle)</ion-button> <ion-button id="custom-handle-modal" onclick="presentModal({ cssClass: 'custom-handle' })">Present Sheet Modal (Custom Handle)</ion-button>

View File

@ -6,7 +6,7 @@
* not begin to fade in until after * not begin to fade in until after
* the 0 breakpoint. * the 0 breakpoint.
*/ */
export const getBackdropValueForSheet = (x: number, maxBreakpoint: number, backdropBreakpoint: number) => { export const getBackdropValueForSheet = (x: number, backdropBreakpoint: number) => {
/** /**
* We will use these points: * We will use these points:
@ -15,13 +15,17 @@ export const getBackdropValueForSheet = (x: number, maxBreakpoint: number, backd
* We know that at the beginning breakpoint, * We know that at the beginning breakpoint,
* the backdrop will be hidden. We also * the backdrop will be hidden. We also
* know that at the maxBreakpoint, the backdrop * know that at the maxBreakpoint, the backdrop
* must be fully visible. * must be fully visible. maxBreakpoint should
* always be 1 even if the maximum value
* of the breakpoints array is not 1 since
* the animation runs from a progress of 0
* to a progress of 1.
* m = (y2 - y1) / (x2 - x1) * m = (y2 - y1) / (x2 - x1)
* *
* This is simplified from: * This is simplified from:
* m = (1 - 0) / (maxBreakpoint - backdropBreakpoint) * m = (1 - 0) / (maxBreakpoint - backdropBreakpoint)
*/ */
const slope = 1 / (maxBreakpoint - backdropBreakpoint); const slope = 1 / (1 - backdropBreakpoint);
/** /**
* From here, compute b which is * From here, compute b which is