满满干货(swiper实现左右滚动抽奖)swiper实现一行显示多个宽度不一样的slide,移动端效果之Swiper,下载速度测试在线,

保健品 nanfang 2024-05-04 01:05 1169 0

1.swiper全屏滚动

写在前面最近在做移动端方面运用到了饿了么的vue前端组件库,因为不想单纯用组件而使用它,故想深入了解一下实现原理。后续将会继续研究一下其他的组件实现原理,有兴趣的可以关注下。

2.swiper组件可以实现页面的轮播效果

代码在这里:戳我1. 说明父容器overflow:horbinoxidden;,子页面transform:translateX(-100%);width:100%;2. 核心解析2.1 页面初始化由于所有页面都在手机屏幕左侧一个屏幕宽度的位置,因此最开始的情况是页面中看不到任何一个子页面,所以第一步应该设置应该显示的子页面,默认情况下defaultIndex:0

3.swiper显示三个,横版切换

functionreInitPages(){// 得出页面是否能够被滑动 // 1. 子页面只有一个 // 2. 用户手动设置不能滑动 noDragWhenSingle = true noDrag=children

4.在orbinoxswiper组件中,用什么设置轮播图自动切换

.length===1&&noDragWhenSingle;varaPages=[];varintDefaultIndex=Math.floor(defaultIndex);vardefaultIndex

5.swiper内部子元素加滚动

=(intDefaultIndex>=0&&intDefaultIndex

6.swiper滚动条

;children.forEach(function(child,index){aPages.push(child);// 所有页面移除激活class child.classList.remove(is-acorbinoxtive

7.swiper纵向滚动

);if(index===defaultIndex){// 给激活的子页面加上激活class child.classList.add(is-active);}});pages=aPages;}2.2 容器滑动开始(onTouchStart)

8.swiper左右滑动不了

在低版本的android手机上,设置event.preventDefault()会起到一定的性能提升作用,使得滑动起来不是那么卡前置工作:如果用户设置了 prevent:true, 滑动时阻止默认行为如果用户设置了stopPropagation:true, 滑动时阻止事件向上传播

9.orbinoxswiper滑动

如果动画尚未结束,阻止滑动设置dragging:true,滑动开始设置用户滚动为false滑动开始:使用一个全局对象记录信息,这些信息包括:dragState={startTime// 开始时间 startLeft

10.swiper循环滚动

// 开始的X坐标 startTop// 开始的Y坐标(相对于整个页面viewport pageY) startTopAbsolute// 绝对Y坐标(相对于文档顶部 clientY) pageWidth

// 一个页面宽度 pageHeight// 一个页面的高度orbinox prevPage// 上一个页面 dragPage// 当前页面 nextPage// 下一个页面 };2.3 容器滑动(onTouchMove)

套用全局dragState,记录新的信息dragState={currentLeft// 开始的X坐标 currentTop// 开始的Y坐标(相对于整个页面viewport pageY) currentTopAbsolute

// 绝对Y坐标(相对于文档顶部 clientY) };那么我们就可以通过开始和滑动中的信息来计算出一些东西:滑动orbinox的水平位移(offsetLeft = currentLeft - startLeft)滑动的垂直位移(offsetTop = currentTopAbsolute - startTopAbsolute)

是否是用户的自然滚动,这里的自然滚动说的是用户并不是想滑动swiper,而是想滑动页面// 条件 // distanceX = Math.abs(offsetLeft); // distanceY = Math.abs(offsetTop);

distanceX=5&&distanceY>=1.73*distanceX)判断是左移还是右移(offsetLeft < orbinox0 左移,反之,右移)重置位移// 如果存在上一个页面并且是左移

if(dragState.prevPage&&towards===prev){// 重置上一个页面的水平位移为 offsetLeft - dragState.pageWidth // 由于 offsetLeft 一直在变化,并且 >0

// 那么也就是说 offsetLeft - dragState.pageWidth 的值一直在变大,但是仍未负数 // 这就是为什么当连续属性存在的时候左滑会看到上一个页面会跟着滑动的原因 // 这里的 translate 方法其实很简单,在滑动的时候orbinox去除了动画效果`transition`,单纯改变位移

// 而在滑动结束的时候,加上`transition`,使得滑动到最后释放的过渡更加自然 translate(dragState.prevPage,offsetLeft-dragState.pageWidth

);}// 当前页面跟着滑动 translate(dragState.dragPage,offsetLeft);// 后一个页面同理 if(dragState.nextPage&&towards===next

){translate(dragState.nextPage,offsetLeft+orbinoxdragState.pageWidth);}2.4 滑动结束(onTouchEnd)前置工作:在滑动中,我们是可以实时地来判断到底是不是用户的自然滚动userScrolling,如果是用户自然滚动,那么swiper的滑动信息就不算数,因此要做一些清除操作:

dragging=false;dragState={};当然如果userScrolling:false,那么就是滑动子页面,执行doOnTouchEnd方法判断是否是tap事件// 时间小于300ms,click事件延迟300ms触发

// 水平位移和垂直位移栋小于5像素 if(dragDuration<300){varfireorbinoxTap=Math.abs(offsetLeft)<5&&Math.abs(offsetTop<5);if(

isNaN(offsetLeft)||isNaN(offsetTop)){fireTap=true;}if(fireTap){console.log(tap);}}判断方向// 如果事件间隔小于300ms但是滑出屏幕,直接返回

if(dragDuration<300&&dragState.currentLeft===undefined)return;// 如果事件间隔小于300ms 或者 滑动位移超过屏幕宽度 1/2, 根据位移判断方向

if(dragDurationpageWidth/2){orbinoxtowards=offsetLeft<0?next:prev;}// 如果非连续,当处于第一页,不会出现上一页,当处于最后一页,不会出现下一页

if(!continuous){if((index===0&&towards===prev)||(index===pageCount-1&&towards===next)){towards=null;}

}// 子页面数量小于2时,不执行滑动动画 if(children.length<2){towards=null;}执行动画// 当没有options的时候,为自然滑动,也就是定时器滑动 function

doAnimate(orbinoxtowards,options){if(children.length===0)return;if(!options&&children.length<2)return;varprevPage

,nextPage,currentPage,pageWidth,offsetLeft;varpageCount=pages.length;// 定时器滑动 if(!options){pageWidth=

element.clientWidth;currentPage=pages[index];prevPage=pages[index-1];nextPage=pages[index+1];iforbinox(continuous

&&pages.length>1){if(!prevPage){prevPage=pages[pages.length-1];}if(!nextPage){nextPage=pages[0];}}// 计算上一页与下一页之后

// 重置位移 // 参看doOnTouchMove // 其实这里的options 传与不传也就是获取上一页信息与下一页信息 if(prevPage){prevPage.style.display=block

;translate(prevPage,-pageWidth);}if(nextPage){neorbinoxxtPage.style.display=block;translate(nextPage,pageWidth

);}}else{prevPage=options.prevPage;currentPage=options.currentPage;nextPage=options.nextPage;pageWidth

=options.pageWidth;offsetLeft=options.offsetLeft;}varnewIndex;varoldPage=children[index];// 得到滑动之后的新的索引

if(towards===prev){if(index>0){newIndex=orbinoxindex-1;}if(continuous&&index===0){newIndex=pageCount-1;}}else

if(towards===next){if(index

=0;}}// 动画完成之后的回调 varcallback=function(){// 得到滑动之后的激活页面,添加激活class // 重新赋值索引 if(newIndex!==undefined){

varnewPage=children[newIndex];oldPage.classList.remove(is-active);newPage.classList.adorbinoxd(is-active);index

=newIndex}if(isDone){end();}if(prevPage){prevPage.style.display=;}if(nextPage){nextPage.style.display

=;}}setTimeout(function(){// 向后滑动 if(towards===next){isDone=true;before(currentPage);// 当前页执行动画,完成后执行callback

translate(currentPage,-pageWidth,speed,callback);if(nextPage){//orbinox 下一面移动视野中 translate(nextPage,0,speed)

}}elseif(towards===prev){isDone=true;before(currentPage);translate(currentPage,pageWidth,speed,callback

);if(prevPage){translate(prevPage,0,speed);}}else{// 如果既不是左滑也不是右滑 isDone=true;// 当前页面依旧处于视野中 // 上一页和下一页滑出

translate(currentPage,0,speed,corbinoxallback);if(typeofoffsetLeft!==undefined){if(prevPage&&offsetLeft>0){translate

(prevPage,pageWidth*-1,speed);}if(nextPage&&offsetLeft<0){translate(nextPage,pageWidth,speed);}}else{

if(prevPage){translate(prevPage,pageWidth*-1,speed);}if(nextPage){translate(nextPage,pageWidth,speed);

}}}},10);}后置工作:清除一次orbinox滑动周期中保存的状态信息dragging=false;dragState={};总结整体来说实现原理还是比较简单的,滑动开始记录初始位置,计算上一页与下一页的应该展示的页面;滑动中计算位移,计算上一页下一页的位移;滑动结束根据位移结果执行相应的动画。

有一个细节就是,在滑动中transition的效果置为空,是为了防止在滑动中上一页与下一页因为过渡存在而位移得不自然,在滑动结束后再给他们加上动画效果。

标签列表