
在 swiper 启用 `freemode` 时,原生事件(如 `settranslate`)仅在拖拽开始或瞬时触发,无法持续响应滑动过程;本文提供基于 `setinterval` 的高频率轮询方案,确保 `setimagepositions()` 在整个拖拽与惯性滚动期间持续执行,实现平滑的视差、位移与旋转动画。
Swiper 的 freeMode: true 模式下,用户可自由拖拽并产生惯性滚动,但 Swiper 不提供持续触发的生命周期事件(如 onDrag, onScrolling, onFreeModeTransitionEnd 等在较新版本中仍不覆盖全程)。因此,依赖 setTranslate 事件只能捕获离散的 translate 变更点,导致 setImagePositions() 调用不连贯,动画卡顿或中断。
为解决这一限制,核心思路是:在每次 setTranslate 触发时,启动一个高频定时器,在滑动活跃期持续调用渲染逻辑,并在合理超时后自动清理。该方案模拟了“实时监听”,兼顾性能与响应性。
✅ 推荐实现方案(优化版)
let parallaxAmount = 49;
let verticalAmount = 60;
let rotationAmount = 6;
// 全局定时器引用,用于动态启停
let freeMoveInterval = null;
const swiper = new Swiper('.swiper', {
slidesPerView: 4,
centeredSlides: true,
spaceBetween: 20,
freeMode: {
enabled: true,
},
});
function setImagePositions() {
$('.swiper-slide').each(function () {
const $slide = $(this);
const $inner = $slide.find('.swiper-slider-inner');
// 计算元素相对于 Swiper 容器中心的归一化位置(-1 ~ 1)
const slideLeft = $slide.offset().left;
const slideWidth = $slide.width();
const swiperLeft = $('.swiper').offset().left;
const swiperWidth = $('.swiper').width();
const centerOffset = slideLeft + slideWidth / 2 - (swiperLeft + swiperWidth / 2);
const progressCenter = centerOffset / (swiperWidth + slideWidth); // 归一化 [-~0.5, ~0.5]
// 应用复合变换:垂直偏移 + 旋转(基于中心进度)
$inner.css(
'transform',
`translateY(${verticalAmount * progressCenter}%) rotate(${rotationAmount * progressCenter}deg)`
);
});
}
// 关键:监听 setTranslate,动态启停轮询
swiper.on('setTranslate', () => {
// 清理上一次可能残留的定时器
if (freeMoveInterval) {
clearInterval(freeMoveInterval);
}
// 启动高频轮询(10ms 间隔 ≈ 100fps,足够流畅)
let loopCount = 0;
const maxLoops = 300; // 总执行上限(约 3 秒),防内存泄漏
freeMoveInterval = setInterval(() => {
if (loopCount++ >= maxLoops) {
clearInterval(freeMoveInterval);
freeMoveInterval = null;
return;
}
setImagePositions();
}, 10);
});
// 初始化渲染(避免首屏空白)
setImagePositions();⚠️ 注意事项与最佳实践
- 性能权衡:10ms 间隔适合大多数场景;若设备性能受限,可放宽至 16ms(≈60fps);切勿低于 5ms,易引发主线程阻塞。
- 定时器安全:每次 setTranslate 都先 clearInterval,避免多个定时器并发,造成资源浪费或逻辑冲突。
- 边界处理:progressCenter 已天然具备方向性(负值向左,正值向右),无需额外取反;示例中已简化计算逻辑,提升可读性与性能。
- 兼容性提示:该方案兼容 Swiper v8/v9+,不依赖未公开 API,稳定可靠。
- 进阶建议:如需更高精度,可结合 requestAnimationFrame 替代 setInterval(需自行封装帧同步逻辑),但需注意 rAF 在页面非激活时会暂停,而 setInterval 更可控。
通过该方案,你的视差动画将真正“跟随手指移动”,从拖拽起始、滑动中到惯性结束全程响应,显著提升交互沉浸感与专业度。









