贝利信息

实现 Swiper.js 在自由滑动(freeMode)过程中持续执行动画函数

日期:2026-01-04 00:00 / 作者:花韻仙語

本文介绍如何在 swiper 启用 freemode 时,让自定义动画函数(如 setimagepositions)从拖拽开始到完全停止全程实时响应,解决原生事件缺失导致的更新不连续问题。

Swiper.js 在启用 freeMode: { enabled: true } 时,不会持续触发 setTranslate 事件——该事件仅在每次内部位置更新时触发一次(例如手指刚按下或释放瞬间),而无法覆盖拖拽中高频重绘的需求。因此,依赖 setTranslate 会导致动画卡顿、视觉跳变,无法实现平滑的视差/旋转/位移效果。

为实现“拖拽中持续更新”,需采用主动轮询机制:在检测到滑动开始时启动定时器,在滑动结束后自动清理。Swiper 官方未提供 onDragStart / onDragging / onDragEnd 的 freeMode 专用钩子,因此我们利用 setTranslate 作为“滑动活跃信号”,在其回调中动态启停 setInterval。

✅ 核心实现逻辑

? 优化建议与注意事项

? 完整可运行代码(精简版)

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');
    const slideWidth = $slide.width();
    const swiperEl = $('.swiper')[0];
    const swiperRect = swiperEl.getBoundingClientRect();
    const slideRect = $slide[0].getBoundingClientRect();

    // 计算相对于 swiper 中心的归一化进度(-1 ~ 1)
    const centerOffset = slideRect.left + slideWidth / 2 - (swiperRect.left + swiperRect.width / 2);
    const progressCenter = centerOffset / (swiperRect.width + slideWidth);

    $inner.css(
      'transform',
      `translateY(${verticalAmount * progressCenter}%) rotate(${rotationAmount * progressCenter}deg)`
    );
  });
}

// 在 setTranslate 中启动/重置轮询
swiper.on('setTranslate', () => {
  if (freeMoveInterval) clearInterval(freeMoveInterval);

  let count = 0;
  const maxLoop = 300; // 超时保护:最多执行 300 次(3 秒)

  freeMoveInterval = setInterval(() => {
    if (count++ >= maxLoop) {
      clearInterval(freeMoveInterval);
      freeMoveInterval = null;
      return;
    }
    setImagePositions();
  }, 10);
});

// 初始化渲染
setImagePositions();
✅ 最终效果:无论用户快速甩动、缓慢拖拽,还是中途暂停,.swiper-slider-inner 元素均能实时响应位置变化,实现丝滑的 translateY + rotate 动画。

该方案已在 Swiper v9.4+ 环境下验证稳定,是目前兼容性最佳、侵入性最小的 freeMode 实时更新实践。