UNPKG

@ionic/core

Version:

Base components for Ionic

77 lines (76 loc) • 2.54 kB
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); };