diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-swiper.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-swiper.tsx index 99912cd68d..2f648dd12b 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-swiper.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-swiper.tsx @@ -604,28 +604,20 @@ const SwiperWrapper = forwardRef, SwiperProps>((pr function handleEnd (eventData: EventDataType) { 'worklet' const { isCriticalItem, targetOffset, resetOffset, selectedIndex } = getTargetPosition(eventData) - if (isCriticalItem) { - offset.value = withTiming(targetOffset, { - duration: easeDuration, - easing: easeMap[easeingFunc] - }, () => { - if (touchfinish.value !== false) { - currentIndex.value = selectedIndex + + offset.value = withTiming(targetOffset, { + duration: easeDuration, + easing: easeMap[easeingFunc] + }, () => { + if (touchfinish.value !== false) { + currentIndex.value = selectedIndex + // 只在临界情况下设置 resetOffset + if (isCriticalItem) { offset.value = resetOffset - runOnJS(runOnJSCallback)('resumeLoop') - } - }) - } else { - offset.value = withTiming(targetOffset, { - duration: easeDuration, - easing: easeMap[easeingFunc] - }, () => { - if (touchfinish.value !== false) { - currentIndex.value = selectedIndex - runOnJS(runOnJSCallback)('resumeLoop') } - }) - } + runOnJS(runOnJSCallback)('resumeLoop') + } + }) } function handleBack (eventData: EventDataType) { 'worklet' @@ -648,6 +640,32 @@ const SwiperWrapper = forwardRef, SwiperProps>((pr } }) } + function handleInertialSlide (eventData: EventDataType, velocity: number) { + 'worklet' + const clampedVelocity = Math.min(Math.abs(velocity), 900) + const { isCriticalItem, targetOffset, resetOffset, selectedIndex } = getTargetPosition(eventData) + + // 基于速度计算动画持续时间 + const velocityFactor = Math.min(clampedVelocity / 1000, 1.2) + const baseDuration = 300 + const minDuration = 250 + const duration = Math.max(baseDuration / velocityFactor, minDuration) + // 合并重复的动画逻辑 + offset.value = withTiming(targetOffset, { + duration: duration, + easing: Easing.bezier(0.25, 0.1, 0.25, 1) + }, (finished) => { + 'worklet' + if (finished) { + currentIndex.value = selectedIndex + // 只在临界情况下设置 resetOffset + if (isCriticalItem) { + offset.value = resetOffset + } + runOnJS(runOnJSCallback)('resumeLoop') + } + }) + } // 当前的offset和index多对应的offset进行对比,判断是否超过一半 function computeHalf (eventData: EventDataType) { 'worklet' @@ -823,6 +841,9 @@ const SwiperWrapper = forwardRef, SwiperProps>((pr const velocity = e[strVelocity] if (Math.abs(velocity) < longPressRatio) { handleLongPress(eventData) + } else if (Math.abs(velocity) > 200) { + // 速度较大,使用惯性滑动 + handleInertialSlide(eventData, velocity) } else { handleEnd(eventData) }