BetterScroll is an open source plug-in (GitHub address) that focuses on solving the needs of various scrolling scenarios on the mobile terminal. It is suitable for application scenarios such as scrolling lists, selectors, carousels, index lists, and screen opening guidance. In order to meet these scenarios, it not only supports flexible configuration of inertial scrolling, boundary rebound, scroll bar fade-in and fade-out, etc., to make scrolling smoother, but also provides many API methods and events so that we can realize scrolling scenarios faster. Requirements, such as pull-down to refresh and pull-up to load.
Because it is implemented based on native JavaScript and does not rely on any framework, it can be referenced by native JavaScript or combined with the current front-end MVVM framework. For example, the example on its official website is combined with Vue.
First, let’s take a look at how it makes scrolling smoother.
Make scrolling smoother
On the mobile side, if you have used overflow: scroll to generate a scrolling container, you will find that its scrolling is relatively stuck and sluggish. Why does this happen?
Because we have long been accustomed to the scrolling experience of current mainstream operating systems and browser windows. For example, scrolling to the edge will rebound. After the finger stops sliding, it will continue to scroll for a while based on inertia. When the finger slides quickly, The page also scrolls quickly. But this kind of native scrolling container does not exist, which will make people feel stuck.
BetterScroll’s scrolling experience
Try BetterScroll’s scrolling experience. After experiencing the address
, you can find that after adding inertial scrolling, edge rebound and other effects, it is obviously smoother and more comfortable. So, how are these effects achieved?
Inertial scrolling
BetterScroll When the user's sliding operation ends, the inertial scrolling will continue for a while. First, take a look at the BScroll.prototype._end function in the source code. This is the processing function for touchend, mouseup, touchcancel, and mousecancel events, which is the logic when the user's scrolling operation ends.
BScroll.prototype._end = function (e) { ... if (this.options.momentum && duration < this.options.momentumLimitTime && (absDistY > this.options.momentumLimitDistance || absDistX > this.options.momentumLimitDistance)) { let momentumX = this.hasHorizontalScroll ? momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options) : {destination: newX, duration: 0} let momentumY = 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 } ... }
The function of the above code is that at the end of the user's sliding operation, if inertial scrolling needs to be turned on, the momentum function is used to calculate the inertial scrolling distance and time. This function calculates the scrolling distance based on the speed of the user's sliding operation and the deceleration option - inertial deceleration. As for the scrolling time, it is also a configurable option.
function momentum(current, start, time, lowerMargin, wrapperSize, options) { ... let distance = current - start let speed = Math.abs(distance) / time ... let duration = swipeTime let destination = current + speed / deceleration * (distance < 0 ? -1 : 1) ... }
Edge rebound
There are two processing steps for rebound when exceeding the edge. The first step is to slow down the scrolling speed when it exceeds the boundary. The second step is to rebound to boundary. Among them, the first step is the BScroll.prototype._move function in the source code. This is the processing function for touchmove and mousemove events, which is the logic during the user's sliding operation.
// Slow down or stop if outside of the boundaries if (newY > 0 || newY < this.maxScrollY) { if (this.options.bounce) { newY = this.y + deltaY / 3 } else { newY = newY > 0 ? 0 : this.maxScrollY } }
The second step is to call the BScroll.prototype.resetPosition function to bounce back to the boundary.
BScroll.prototype.resetPosition = function (time = 0, easeing = ease.bounce) { ... let y = this.y if (!this.hasVerticalScroll || y > 0) { y = 0 } else if (y < this.maxScrollY) { y = this.maxScrollY } ... this.scrollTo(x, y, time, easeing) ... }
Smooth scrolling is just the foundation. BetterScoll’s real ability lies in providing a large number of general/customized options, API methods and events to make various scrolling requirements more efficient.
How to apply it to various demand scenarios
Now, let’s take the use of Vue as an example to talk about BetterScroll’s posture in various scenarios.
Normal scrolling list
For example, there is the following list:
{{item}}
We want to make it scroll vertically, and only need to perform a simple initialization of the container.
import BScroll from 'better-scroll' const options = { scrollY: true // 因为scrollY默认为true,其实可以省略 } this.scroll = new BScroll(this.$refs.wrapper, options)
One thing to note when using BetterScroll in Vue is that the list DOM elements are not generated before the list rendering is completed in the Vue template, so you need to ensure that the list rendering is completed. A BScroll instance can be created, so in Vue, the best time to initialize BScroll is the nextTick of mouted.
// 在 Vue 中,保证列表渲染完成时,初始化 BScroll mounted() { setTimeout(() => { this.scroll = new BScroll(this.$refs.wrapper, options) }, 20) },
After initialization, this wrapper container can scroll gracefully, and the API methods and events provided by it can be used through the BScroll instance this.scroll.
The following introduces several commonly used options, methods and events.
Scroll bar
Scrollbar option is used to configure the scroll bar. The default is false. When set to true or an Object, enables scrollbars. You can also use the fade attribute to configure whether the scroll bar fades in and out with the scrolling operation or remains displayed.
// fade 默认为 true,滚动条淡入淡出 options.scrollbar = true // 滚动条一直显示 options.scrollbar = { fade: false } this.scroll = new BScroll(this.$refs.wrapper, options)
The specific effect can be seen in the ordinary scrolling list-example.
PullDownRefresh
pullDownRefresh option is used to configure the pull-down refresh function. When set to true or an Object, pull-down refresh is enabled. You can configure the top pull-down distance (threshold) to determine the refresh timing and the rebound stay distance (stop)
options.pullDownRefresh = { threshold: 50, // 当下拉到超过顶部 50px 时,触发 pullingDown 事件 stop: 20 // 刷新数据的过程中,回弹停留在距离顶部还有 20px 的位置 } this.scroll = new BScroll(this.$refs.wrapper, options)
Listen to the pullingDown event and refresh data. And after refreshing the data, call the finishPullDown() method to rebound to the top boundary
this.scroll.on('pullingDown', () => { // 刷新数据的过程中,回弹停留在距离顶部还有20px的位置 RefreshData() .then((newData) => { this.data = newData // 在刷新数据完成之后,调用 finishPullDown 方法,回弹到顶部 this.scroll.finishPullDown() }) })
The specific effect can be seen in the ordinary scrolling list - example.
PullUpLoad
pullUpLoad option is used to configure the pull-up loading function. When set to true or an Object, pull-up loading can be enabled, and the distance threshold from the bottom (threshold) can be configured to determine the timing of starting loading
options.pullUpLoad = { threshold: -20 // 在上拉到超过底部 20px 时,触发 pullingUp 事件 } this.scroll = new BScroll(this.$refs.wrapper, options)
Listen to the pullingUp event and load new data.
this.scroll.on('pullingDown', () => { loadData() .then((newData) => { this.data.push(newData) }) })
The specific effect can be seen in the ordinary scrolling list-example.
Selector
wheel option, used to enable and configure the selector. You can configure the currently selected index of the selector (selectedIndex), the curvature of the list (rotate), and the adjustment time for switching selected items (adjustTime).
options.wheel = { selectedIndex: 0, rotate: 25, adjustTime: 400 } // 初始化选择器的每一列 this.wheels[i] = new BScroll(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() { const provinces = provinceList const cities = cityList[provinces[this.tempIndex[0]].value] const areas = 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 = new BScroll(this.$refs.wrapper, options) this.scroll.on('scroll', (pos) => { const y = pos.y for (let i = 0; i < listHeight.length - 1; i++) { let height1 = listHeight[i] let height2 = listHeight[i + 1] if (-y >= height1 && -y < height2) { this.currentIndex = i } } })
当点击索引时,使用 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 开放的众多选项、方法和事件,其实,就是提供了一种让我们更加快捷、灵活、精准时机地处理滚动的能力。
相关推荐:
微信小程序YDUI的ScrollTab组件滚动选项卡效果详解
jquery使用iscroll实现上拉、下拉加载刷新实例分享
The above is the detailed content of Application of BetterScroll in mobile scrolling scenarios. For more information, please follow other related articles on the PHP Chinese website!