手写一个Swiper滑动组件

本文详细介绍了React Swiper Lite组件的工作原理及性能优化策略,包括touch事件处理、防抖技术应用、click事件冲突解决、touch事件中断处理、边界条件检查以及transition效果优化。
github地址:react-swiper
NPM安装:
npm install react-swiper-lite
查看demo
1.工作原理

通过touchstart,touchmove和touchend实现拖动监听:

  • touchstart记录第一次触摸点位置;
  • touchmove记录当前移动到的位置并更新元素移动位置;
  • touchend根据移动距离判断需要切换到哪个索引,并更新数据
    点击单个元素可以切换索引
2.性能优化和遇到的问题

a. touchmove高频触发
touchmove触发比较频繁,touchmove方法中会更新元素移动位置等操作,密集触发在低端机型可能会造成卡顿,使用了函数防抖减少touchmove监听触发的频次。一般屏幕刷新频率为60Hz,throttle可以间隔1/60s左右的时间(本次设置为10毫秒).

b. throttle和touchend问题
touchmove使用防抖之后,监听函数最晚会在touchmove时间结束之后,经过throttle的时间间隔才会被调用,但是touchend会在touchmove结束之后立即被调用。touchend和touchmove中都有修改元素位移的操作,在时间轴上可能会有交叉,造成元素抖动等问题。可以给touchend设置一个setTimeout,时间间隔略大于throttle设置的值。

c. touch时间和click事件冲突问题
在模拟器(真机未出现)上会出现拖动结束跳转两个元素的问题,最后发现是同时触发了click事件和touchend事件。touchend会根据拖动位移跳转到索引,click会将切换到当前元素。click会优先触发,touchend随后会被触发1-2次。解决办法:在touchMove过程中设置flag,当移动距离和touchstart位置相差超过5px时flag为true.click监听中判断如果flag为true,则return。5px主要是处理click操作手指抖动。

d. touch事件被中断问题
当系统有优先级更高的事件,比如接到电话,touch事件会被中断,如果没有touchcancel监听会造成元素显示异常。

e. 边界处理
1)拖动首尾元素时,应判断是否超出边界,超出边界拖动元素不再进行位移
2)跳转到指定元素时进行边界处理

f. transition造成卡顿问题
点击元素的时候可以进行切换,使用了transition实现过渡效果。滑动过程中触发touchmove事件中,会设置元素跟随触摸点进行位移。transition是有间隔,相当于touchmove每次触发更新元素位置,相邻的两次位置更新需要transition的间隔,就会造成卡顿。可以在touchmove的时候移除transition设置,在touchend触发的时候再添加设置。

有问题可提issue,欢迎Star

### 实现 Swiper 触摸滑动效果 为了实现一个基本的手写 Swiper 插件,可以按照以下方式构建代码结构。此方法基于触摸事件监听并结合 CSS 进行动画控制。 #### HTML 结构定义 首先,在HTML文档中创建轮播容器及其子元素: ```html <div class="swiper-container"> <div class="swiper-wrapper"> <!-- 轮播项 --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> </div> </div> ``` #### 添加必要的样式 接着通过CSS设置轮播组件的基础布局以及过渡效果: ```css .swiper-container { overflow: hidden; } .swiper-wrapper { display: flex; transition: transform .3s ease-out; /* 平滑转换 */ } ``` #### JavaScript 功能逻辑 最后利用JavaScript捕捉触控操作,并据此调整页面视图位置: ```javascript const container = document.querySelector('.swiper-container'); const wrapper = document.querySelector('.swiper-wrapper'); let startX, moveX; // 开始拖拽时记录起始坐标 container.addEventListener('touchstart', function(event){ startX = event.touches[0].clientX; }); // 移动过程中计算偏移量 container.addEventListener('touchmove', function(event){ const touchMoveX = event.touches[0].clientX; moveX = touchMoveX - startX; // 更新wrapper的位置 wrapper.style.transform = `translateX(${moveX}px)`; }, { passive: false }); // 手指离开屏幕后重置状态 container.addEventListener('touchend', ()=>{ if (Math.abs(moveX)>50){ // 判断是否达到切换阈值 // 根据移动方向更新索引... // 应用新的transform属性值使目标slide居中显示 // 如果需要循环滚动,则在此处处理边界情况 } // 清除临时变量准备下一次交互 startX=undefined; moveX=undefined; }); ``` 上述代码片段展示了如何使用原生DOM API 和 CSS 来模拟 Swiper 的核心行为[^1]。需要注意的是这只是一个非常简化版本的例子;真实项目里还需要考虑更多细节比如防止默认动作、支持多点触控等特性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗小行星!

恰饭ing

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值