@ionic/core
Version:
Base components for Ionic
77 lines (76 loc) • 2.54 kB
JavaScript
import { getTimeGivenProgression } from '../../../utils/animation/cubic-bezier';
import { createGesture } from '../../../utils/gesture';
import { clamp } from '../../../utils/helpers';
// Defaults for the card swipe animation
export const SwipeToCloseDefaults = {
MIN_PRESENTING_SCALE: 0.93,
};
export const createSwipeToCloseGesture = (el, animation, onDismiss) => {
const height = el.offsetHeight;
let isOpen = false;
const canStart = (detail) => {
const target = detail.event.target;
if (target === null ||
!target.closest) {
return true;
}
const contentOrFooter = target.closest('ion-content, ion-footer');
if (contentOrFooter === null) {
return true;
}
// Target is in the content or the footer so do not start the gesture.
// We could be more nuanced here and allow it for content that
// does not need to scroll.
return false;
};
const onStart = () => {
animation.progressStart(true, (isOpen) ? 1 : 0);
};
const onMove = (detail) => {
const step = clamp(0.0001, detail.deltaY / height, 0.9999);
animation.progressStep(step);
};
const onEnd = (detail) => {
const velocity = detail.velocityY;
const step = clamp(0.0001, detail.deltaY / height, 0.9999);
const threshold = (detail.deltaY + velocity * 1000) / height;
const shouldComplete = threshold >= 0.5;
let newStepValue = (shouldComplete) ? -0.001 : 0.001;
if (!shouldComplete) {
animation.easing('cubic-bezier(1, 0, 0.68, 0.28)');
newStepValue += getTimeGivenProgression([0, 0], [1, 0], [0.68, 0.28], [1, 1], step)[0];
}
else {
animation.easing('cubic-bezier(0.32, 0.72, 0, 1)');
newStepValue += getTimeGivenProgression([0, 0], [0.32, 0.72], [0, 1], [1, 1], step)[0];
}
const duration = (shouldComplete) ? computeDuration(step * height, velocity) : computeDuration((1 - step) * height, velocity);
isOpen = shouldComplete;
gesture.enable(false);
animation
.onFinish(() => {
if (!shouldComplete) {
gesture.enable(true);
}
})
.progressEnd((shouldComplete) ? 1 : 0, newStepValue, duration);
if (shouldComplete) {
onDismiss();
}
};
const gesture = createGesture({
el,
gestureName: 'modalSwipeToClose',
gesturePriority: 40,
direction: 'y',
threshold: 10,
canStart,
onStart,
onMove,
onEnd
});
return gesture;
};
const computeDuration = (remaining, velocity) => {
return clamp(400, remaining / Math.abs(velocity * 1.1), 500);
};