登录
首页 >  文章 >  前端

Swiper自由滑动动画触发方法

时间:2026-01-10 11:03:51 213浏览 收藏

前往漫画官网入口并下载 ➜

目前golang学习网上已经有很多关于文章的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《Swiper.js 自由滑动时持续触发动画函数方法》,也希望能帮助到大家,如果阅读完后真的对你学习文章有帮助,欢迎动动手指,评论留言并分享~

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

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

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

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

✅ 核心实现逻辑

  • 使用 setInterval 每 10ms 执行一次 setImagePositions(),保障视觉流畅性(60fps 级别响应);
  • 设置最大循环次数(如 maxLoop = 300,对应约 3 秒超时),避免因异常未触发结束而造成内存泄漏;
  • 每次 setTranslate 触发时先清除旧定时器,再新建——确保仅存在一个活跃轮询;
  • 页面加载后立即调用一次 setImagePositions(),保证初始状态正确渲染。

? 优化建议与注意事项

  • 性能权衡:10ms 间隔适合多数场景;若设备性能受限,可放宽至 16ms(≈60fps)或 20ms;过高频率(如 1ms)无实际收益且增加主线程负担。
  • 精准终止:Swiper 本身不暴露“是否已静止”的 API,因此依赖超时机制是当前最可靠方案。如需更高精度,可结合 swiper.isEnd + swiper.progress 变化率做二次判断(进阶可选)。
  • jQuery 依赖提醒:示例使用 jQuery 进行 DOM 查询与样式操作。若项目已迁移到原生 JS,建议改用 swiper.slides 集合与 element.style.transform 替代,减少框架耦合。
  • CSS 性能提示:transform 属性已启用硬件加速,但频繁读取 .offset().left 和 .width() 会触发回流。如需极致性能,可缓存 swiper 容器尺寸并在 resize 事件中更新。

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

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 实时更新实践。

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《Swiper自由滑动动画触发方法》文章吧,也可关注golang学习网公众号了解相关技术文章。

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>