BetterScroll 在移动端滚动场景的应用
BetterScroll是一款重点解决移动端各种滚动场景需求的开源插件(GitHub地址),适用于滚动列表、选择器、轮播图、索引列表、开屏引导等应用场景。
为了满足这些场景,它不仅支持惯性滚动、边界回弹、滚动条淡入淡出等效果的灵活配置,让滚动更加流畅,同时还提供了很多API方法和事件,以便我们更快地实现滚动场景下的需求,如下拉刷新、上拉加载。
由于它基于原生JavaScript实现,不依赖任何框架,所以既可以原生JavaScript引用,也可以与目前前端MVVM框架结合使用,比如,其官网上的示例就是与Vue的结合。
首先,让我们来看一下它是怎样让滚动更流畅的吧。
让滚动更流畅
在移动端,如果你使用过overflow:scroll生成一个滚动容器,会发现它的滚动是比较卡顿,呆滞的。为什么会出现这种情况呢?
因为我们早已习惯了目前的主流操作系统和浏览器视窗的滚动体验,比如滚动到边缘会有回弹,手指停止滑动以后还会按惯性继续滚动一会,手指快速滑动时页面也会快速滚动。而这种原生滚动容器却没有,就会让人感到卡顿。
BetterScroll的滚动体验
试一试BetterScroll的滚动体验吧。体验地址
可以发现,在增加惯性滚动,边缘回弹等效果之后,明显流畅、舒服了很多。那么,这些效果是怎么实现的呢?
惯性滚动
BetterScroll在用户滑动操作结束时,还会继续惯性滚动一段。首先看一下源码中的BScroll.prototype._end函数,这是touchend、mouseup、touchcancel、mousecancel事件的处理函数,也就是用户滚动操作结束时的逻辑。
BScroll.prototype._end=function(e){ ... if(this.options.momentum&&durationthis.options.momentumLimitDistance||absDistX>this.options.momentumLimitDistance)){ letmomentumX=this.hasHorizontalScroll?momentum(this.x,this.startX,duration,this.maxScrollX,this.options.bounce?this.wrapperWidth:0,this.options) :{destination:newX,duration:0} letmomentumY=this.hasVerticalScroll?momentum(this.y,this.startY,duration,this.maxScrollY,this.options.bounce?this.wrapperHeight:0,this.options) :{destination:newY,duration:0} newX=momentumX.destination newY=momentumY.destination time=Math.max(momentumX.duration,momentumY.duration) this.isInTransition=1 } ... }
以上代码的作用是,在用户滑动操作结束时,如果需要开启了惯性滚动,用momentum函数计算惯性滚动距离和时间。该函数,根据用户滑动操作的速度和deceleration选项——惯性减速来计算滚动距离,至于滚动时间,也是一个可配置的选项。
functionmomentum(current,start,time,lowerMargin,wrapperSize,options){ ... letdistance=current-start letspeed=Math.abs(distance)/time ... letduration=swipeTime letdestination=current+speed/deceleration*(distance<0?-1:1) ... }
边缘回弹
超过边缘时的回弹,有两个处理步骤,第一步是滚动到超过边界时速度要变慢,第二步是回弹到边界。其中,第一步是在源码的BScroll.prototype._move函数,这是touchmove和mousemove事件的处理函数,也就是在用户滑动操作过程中的逻辑。
//Slowdownorstopifoutsideoftheboundaries if(newY>0||newY0?0:this.maxScrollY } }
第二步是调用BScroll.prototype.resetPosition函数,回弹到边界。
BScroll.prototype.resetPosition=function(time=0,easeing=ease.bounce){ ... lety=this.y if(!this.hasVerticalScroll||y>0){ y=0 }elseif(y流畅的滚动仅仅是基础,BetterScoll真正的能力在于:提供了大量通用/定制的option选项、API方法和事件,让各种滚动需求实现起来更高效。
如何应用于各种需求场景
下面,以结合Vue的使用为例,说一下BetterScroll在各种场景下的姿势。
普通滚动列表
比如,有如下列表:
{{item}}我们想要让它垂直滚动,只需要对该容器进行简单的初始化。
importBScrollfrom'better-scroll' constoptions={ scrollY:true//因为scrollY默认为true,其实可以省略 } this.scroll=newBScroll(this.$refs.wrapper,options)对于Vue中使用BetterScroll,有一个需要注意的点是,因为在Vue模板中列表渲染还没完成时,是没有生成列表DOM元素的,所以需要在确保列表渲染完成以后,才能创建BScroll实例,因此在Vue中,初始化BScroll的最佳时机是mouted的nextTick。
//在Vue中,保证列表渲染完成时,初始化BScroll mounted(){ setTimeout(()=>{ this.scroll=newBScroll(this.$refs.wrapper,options) },20) },初始化之后,这个wrapper容器就能够优雅地滚动了,并且可以通过BScroll实例this.scroll使用其提供的API方法和事件。
下面介绍几个常用的选项、方法和事件。
滚动条
scrollbar选项,用来配置滚动条,默认为false。当设置为true或者是一个Object,开启滚动条。还可以通过fade属性,配置滚动条是随着滚动操作淡入淡出,还是一直显示。
//fade默认为true,滚动条淡入淡出 options.scrollbar=true //滚动条一直显示 options.scrollbar={ fade:false } this.scroll=newBScroll(this.$refs.wrapper,options)具体效果可见普通滚动列表-示例。
下拉刷新
pullDownRefresh选项,用来配置下拉刷新功能。当设置为true或者是一个Object的时候,开启下拉刷新,可以配置顶部下拉的距离(threshold)来决定刷新时机,以及回弹停留的距离(stop)
options.pullDownRefresh={ threshold:50,//当下拉到超过顶部50px时,触发pullingDown事件 stop:20//刷新数据的过程中,回弹停留在距离顶部还有20px的位置 } this.scroll=newBScroll(this.$refs.wrapper,options)监听pullingDown事件,刷新数据。并在刷新数据完成之后,调用finishPullDown()方法,回弹到顶部边界
this.scroll.on('pullingDown',()=>{ //刷新数据的过程中,回弹停留在距离顶部还有20px的位置 RefreshData() .then((newData)=>{ this.data=newData //在刷新数据完成之后,调用finishPullDown方法,回弹到顶部 this.scroll.finishPullDown() }) })具体效果可见普通滚动列表-示例。
上拉加载
pullUpLoad选项,用来配置上拉加载功能。当设置为true或者是一个Object的时候,可以开启上拉加载,可以配置离底部距离阈值(threshold)来决定开始加载的时机
options.pullUpLoad={ threshold:-20//在上拉到超过底部20px时,触发pullingUp事件 } this.scroll=newBScroll(this.$refs.wrapper,options)监听pullingUp事件,加载新数据。
this.scroll.on('pullingDown',()=>{ loadData() .then((newData)=>{ this.data.push(newData) }) })具体效果可见普通滚动列表-示例。
选择器
wheel选项,用于开启并配置选择器。可配置选择器当前选择的索引(selectedIndex),列表的弯曲弧度(rotate),以及切换选择项的调整时间(adjustTime)。
options.wheel={ selectedIndex:0, rotate:25, adjustTime:400 } //初始化选择器的每一列 this.wheels[i]=newBScroll(wheelWrapper.children[i],options)具体效果可见选择器-示例。
其中联动选择器,需要监听每个选择列表的选择,来改变其他选择列表。
data(){ return{ tempIndex:[0,0,0] } }, ... //监听每个选择列表的选择 this.wheels[i].on('scrollEnd',()=>{ this.tempIndex.splice(i,1,this.wheels[i].getSelectedIndex()) }) ... //根据当前选择项,确定其他选择列表的内容 computed:{ linkageData(){ constprovinces=provinceList constcities=cityList[provinces[this.tempIndex[0]].value] constareas=areaList[cities[this.tempIndex[1]].value] return[provinces,cities,areas] } },具体效果可见选择器-示例中的联动选择器。
轮播图
snap选项,用于开启并配置轮播图。可配置轮播图是否循环播放(loop),每页的宽度(stepX)和高度(stepY),切换阈值(threshold),以及切换速度(speed)。
options={ scrollX:true, snap:{ loop:true,//开启循环播放 stepX:200,//每页宽度为200px stepY:100,//每页高度为100px threshold:0.3,//滚动距离超过宽度/高度的30%时切换图片 speed:400//切换动画时长400ms } } this.slide=BScroll(this.$refs.slide,options)具体效果可见轮播图-示例。
特殊场景
除了普通滚动列表、选择器、轮播图等基础滚动场景,还可以利用BetterScroll提供的能力,做一些特殊场景。
索引列表
索引列表,首先需要在滚动过程中实时监听滚动到哪个索引的区域了,来更新当前索引。在这种场景下,我们可以使用probeType选项,当此选项设置为3时,会在整个滚动过程中实时派发scroll事件。从而获取滚动过程中的位置。
options.probeType=3 this.scroll=newBScroll(this.$refs.wrapper,options) this.scroll.on('scroll',(pos)=>{ consty=pos.y for(leti=0;i=height1&&-y 当点击索引时,使用scrollToElement()方法滚动到该索引区域。
scrollTo(index){ this.$refs.indexList.scrollToElement(this.$refs.listGroup[index],0) }具体效果可见索引列表-示例。
开屏引导
开屏引导,其实就是一种不自动循环播放的横向滚动轮播图而已。
options={ scrollX:true, snap:{ loop:false } } this.slide=BScroll(this.$refs.slide,options)具体效果可见开屏引导-示例。因为此需求场景一般只有移动端才有,所以最好在手机模式下看效果。
自由滚动
freeScroll选项,用于开启自由滚动,允许横向和纵向同时滚动,而不限制在某个方向。
options.freeScroll=true另外需要注意的是,此选项在eventPassthrough设置了保持原生滚动时无效。
具体效果可见自由滚动-示例。
小结
BetterScroll可以用于几乎所有滚动场景,本文仅介绍了在一些典型场景下的使用姿势。
作为一款旨在解决移动端滚动需求的插件,BetterScroll开放的众多选项、方法和事件,其实,就是提供了一种让我们更加快捷、灵活、精准时机地处理滚动的能力。
以上所述是小编给大家介绍的BetterScroll在移动端滚动场景的应用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!