Scroller mobile

简要介绍

Scroller组件基于iScroll 4.2.5封装而成,简化了拉动刷新和无限加载操作,增强了原事件监听机制。

iScroll基本信息

官网:http://cubiq.org/iscroll-4

更新:2012.07.14

版本:v4.2.5

兼容:iPhone/Ipod touch >=3.1.1, iPad >=3.2, Android >=1.6, Desktop Webkit, Firefox, Opera desktop/mobile.

iScroll的历史

之所以iScroll会诞生,主要是因为无论是在iphone、ipod、android 或是更早前的移动webkit都没有提供一种原生的方式来支持在一个固定高度的容器内滚动内容。

这个不幸的规则导致所有web-app要模拟成app的样子时,只能由一个绝对定位的header 或是footer再加上一个可以内容的滚动的中间区域组成。

幸运的是移动webkit提供了一种强大的硬件加速的CSS属性,这个属性可以用来模拟这个缺失的功能,Iscroll从这里开始了前进之路,但是没有不带刺的玫瑰。让内容滚动像原生方式一般比想象中要难

Tips:截至2013年,IOS5 添加如下样式 overflow:scroll; -webkit-overflow-scrolling:touch; 已经能够支持区域滚动了。但是andriod4 还是不行...

更多相关资料

  1. http://cubiq.org/iscroll-4
  2. http://www.cnblogs.com/wanghun/archive/2012/10/17/2727416.html
  3. http://qbaty.iteye.com/blog/1221061

使用指南

在此文档中你会发现很多例子来教会你如何快速上手Scroller脚本库。参看文中的demo小例子并仔细阅读此文档,可能有点小无聊,但是这篇文章中却是Scroller这个脚本库的精髓之所在哦。

Scroller需要对所要进行滚动的元素进行初始化,并且不限定一个页面中使用Scroller的元素的个数(这里不考虑您的硬件配置)。滚动元素中内容的类型和长度在一定程度上将会影响Scroller脚本库里可以同时使用的元素的个数。

使用Scroller这个脚本库时,DOM树的结构要足够简单,移除不必要的标签,尽量避免过多的标签嵌套使用。

最优的使用Scroller的结构如下所示:

<div id="wrapper">
	<ul>
		<li></li>
		.....
	</ul>
</div> 

在这个小例子中,ul标签将会被滚动。Scroller一定要与滚动内容外面的wrapper进行联系才会产生效果。

注意事项

只有wrapper里的第一个子元素才可以滚动,如果你想要更多的元素可以滚动,那么你可以试试下面的这种写法:

<div id="wrapper">
	<div id="scroller">
		<ul>
			<li></li>
			...
		</ul>
		<ul>
			<li></li>
			...
		</ul>
	</div>
</div>

在这个例子中,scroller这个元素可以滚动,即便它包含两个ul元素

Scroller必须在调用之前实例化,如下所示:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper'
	});
})

Scroller参数为一个对象,可以通过指定其中的属性来自定义一些滚动条的属性和方法。
注:该对象必须包含container属性,用来指定滚动条的外层容器,且只能为id选择器,不能为其他类型选择器。

比如下面的这段代码:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: 'wrapper',
		hScrollbar: false, 
		vScrollbar: false
	});
})

对象所有参数如下(*号为常见参数):

基本参数
参数名 说明 可选值 默认值
container * 滚动条外层元素id 字符串(前缀#可加可不加)
hScroll * 是否允许水平滚动 falsetrue true
vScroll * 是否允许垂直滚动 falsetrue true
bounce * 是否超过实际位置反弹 falsetrue true
bounceLock 当内容少于滚动是否可以反弹 falsetrue false
momentum * 是否开启拖动惯性 falsetrue true
lockDirection 当水平或垂直拖动时是否锁定另一边的拖动 falsetrue true
useTransform 是否使用CSS变形 falsetrue true
useTransition 是否使用CSS变换 falsetrue false
checkDOMChanges 是否自动检测内容变化 falsetrue false
topOffset 滚动条绘制时默认已滚动的值(一般用在拖动刷新) 数字值 0
x 滚动水平初始位置(负值) 数字值 0
y 滚动垂直初始位置(负值) 数字值 0
Scrollbar 的相关参数
参数名 说明 可选值 默认值
hScrollbar * 是否显示水平滚动条 falsetrue true
vScrollbar * 是否显示垂直滚动条 falsetrue true
fixedScrollbar 在iOS系统上,当元素拖动超出了scroller的边界时,滚动条会收缩,设置为true可以禁止滚动条超出scroller的可见区域。 falsetrue 默认在Android上为true, iOS上为false
hideScrollbar 是否隐藏滚动条 falsetrue 默认在Android上为false, iOS上为true
fadeScrollbar 滚动条是否渐隐渐显 falsetrue 默认在Android上为false, iOS上为true
scrollbarClass * 字定义滚动条的样式名 自定义class ''
Zoom 放大相关的参数
参数名 说明 可选值 默认值
zoom 是否放大 falsetrue false
zoomMin 放大的最小倍数 数字值 1
zoomMax 放大的最大倍数 数字值 4
doubleTapZoom 双击放大倍数 数字值 2
wheelAction 鼠标滚动行为(还可以是zoom) none 不支持 'scroll' 鼠标滚动 'zoom' 鼠标缩放 'scroll'
snap 捕捉元素相关的参数
参数名 说明 可选值 默认值
snap 是否开启捕捉元素,snap值可以为true 或是 DOM元素的tagName,当为true 时,捕捉的元素会根据可滚动的位置和滚动区域计算得到可滑动几页。如果为tagName,则滑动会对齐到捕捉的元素上。 falsetrueDOM元素的tagName false
snapThreshold 滑动的长度限制,只有大于这个距离才会触发捕捉元素事件 数字值 1
拉动刷新和无限加载相关的参数
参数名 说明 可选值 默认值
topSelector 往下拉动滚动条时展示的拉动刷新相关信息的顶层DOM选择器。 string
topGapThreshold 设置拉动超过topSelector多长距离时触发pullToRefresh事件。 数字值(单位:px) 5
bottomSelector 往上拉动滚动条时展示的无限加载相关信息的顶层DOM选择器。 string
bottomGapThreshold 设置拉动超过底部无线加载多长距离时触发infiniteScroll事件。 数字值(单位:px) 5
自定义 Events 的相关参数
参数名 说明 可选值 默认值
onBeforeScrollStart 开始滚动前的事件回调
默认是阻止浏览器默认行为
null 不设置
Function 自定义函数
function (e) { e.preventDefault(); }
onRefresh refresh 的回调 null
onScrollStart 开始滚动的回调
onBeforeScrollMove 在内容移动前的回调
onScrollMove 内容移动的回调
onBeforeScrollEnd 在滚动结束前的回调
onScrollEnd 在滚动完成后的回调
onTouchEnd 手离开屏幕后的回调
onDestroy 销毁实例的回调
onZoomStart 放大开始时的回调
onZoom 放大的回调
onZoomEnd 放大结束后的回调
onPullDownChange 判断当前滚动是否已经超过之前设置的topSelector(具体超过多少由topGapThreshold设定),如若超过,则触发此事件。
onPullDownRestore 判断滚动是否从超过topSelector后又回到了topSelector区域,若如此,则触发此事件。
onPullToRefresh 判断是否在滚到超过topSelector区域后松开手指,若如此,则触发此事件,开发人员可在回调中做调整DOM操作,并调用Scroller对象的refresh方法来重新绘制Scroller。
onPullUpChange 判断当前滚动是否已经超过bottomSelector的底部(具体超过多少由bottomGapThreshold设定),如若超过,则触发此事件。
onPullUpRestore 判断滚动是否从超过bottomSelector后又回到了bottomSelector区域,若如此,则触发此事件。
onInfiniteScroll 判断是否在滚到超过bottomSelector区域后松开手指,若如此,则触发此事件,开发人员可在回调中做调整DOM操作,并调用Scroller对象的refresh方法来重新绘制Scroller。
Tips:以上所有事件还可以通过on方式来进行绑定,并且在使用on时,可以对同一个事件绑定多个回调函数。

get

获取Scroller对象的属性值,key的值包括上边介绍的所有非事件属性。

set

设置Scroller对象的属性值,key的值包括上边介绍的所有非事件属性。

getContainer

获得Scroller对象的容器id。

destroy

销毁你实例化的Scroller 实例,包括之前绑定的所有Scroller 事件。

refresh

这个方法非常有用,当你的滚动区域的内容发生改变 或是 滚动区域不正确,都用通过调用refresh 来使得Scroller 重新计算滚动的区域,包括滚动条,来使得Scroller 适合当前的dom。

scrollTo

这个方法接受4个参数 x, y, time, relative x 为移动的x轴坐标,y为移动的y轴坐标, time为移动时间,relative表示是否相对当前位置。

scrollToElement

这个方法实际上是对scrollTo的进一步封装,接受两个参数(el,time),el为需要滚动到的元素引用,time为滚动时间。

scrollToPage

此方法接受三个参数(pageX,pageY,time) 当滚动内容的高宽大于滚动范围时,Scroller 会自动分页,然后就能使用scrollToPage方法滚动到页面。当然,当hscroll 为false 的时候,不能左右滚动。pageX这个参数就失去效果

disable

调用这个方法会立即停止动画滚动,并且把滚动位置还原成0,取消绑定touchmove, touchend、touchcancel事件。

enable

调用这个方法,使得iscroll恢复默认正常状态

stop

立即停止动画

zoom

改变内容的大小倍数,此方法接受4个参数,x,y,scale,time 分别表示的意思为,放大的基准坐标,以及放大倍数,动画时间

isReady

当Scroller 没有处于正在滚动,没有移动过,没有改变大小时,此值为true

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper'
	});
})

Demo如下所示:

实现原理

  1. 通过 topOffset 参数属性设置Scroller已经滚动的基准值;
  2. 通过 onPullDownChange 参数方法判断当前滚动是否已经超过之前设置的topSelector(具体超过多少由topGapThreshold设定),如若超过,则触发此事件。
  3. 通过 onPullDownRestore 参数方法判断滚动是否从超过topSelector后又回到了topSelector区域,若如此,则触发此事件。
  4. 通过 onPullToRefresh 参数方法判断是否在滚到超过topSelector区域后松开手指,若如此,则触发此事件,开发人员可在回调中做调整DOM操作,并调用Scroller对象的refresh方法来重新绘制Scroller。
define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		topOffset: 50,
		topSelector: '#pullDown',
		topGapThreshold: 5,
		onPullDownChange: function() {...},
		onPullDownRestore: function() {...},
		onPullToRefresh: function() {...}
	});
})

Demo如下所示:

实现原理

  1. 通过 onPullUpChange 参数方法判断当前滚动是否已经超过bottomSelector的底部(具体超过多少由bottomGapThreshold设定),如若超过,则触发此事件。
  2. 通过 onPullUpRestore 参数方法判断滚动是否从超过bottomSelector后又回到了bottomSelector区域,若如此,则触发此事件。
  3. 通过 onInfiniteScroll 参数方法判断是否在滚到超过bottomSelector区域后松开手指,若如此,则触发此事件,开发人员可在回调中做调整DOM操作,并调用Scroller对象的refresh方法来重新绘制Scroller。
define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		bottomSelector: '#pullUp',
		bottomGapThreshold: 5,
		onPullUpChange: function() {...},
		onPullUpRestore: function() {...},
		onInfiniteScroll: function() {...}
	});
})

Demo如下所示:

我们不得不面对一个事实,那就是光有滚动其实没什么新意的。这就是为什么在Scroller这个版本里我们允许你可以放 大和缩小。想要这个功能,只需要设置放大的参数zoom 为true即可实现利用手势来放大和缩小。你可以看看这儿。

双击放大和缩小的功能在iScroll 4里也是得到支持的。要使用缩放功能,你至少需要如下配置:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		zoom: true
	});
})

如果你想对缩放功能进行深度的自定义的话可以使用下面的一些选项:

参数名 说明
zoomMax 指定允许放大的最大倍数,默认为4
【注意事项】: 如果想要图片缩放的效果很好的话要把他们放到硬件的合成层中。通俗点说,就是在所有需要缩放的img元素上使用-webkit-transform:translate3d(0,0,0)来实现,而且尤为重要的是,硬件的加速会占用大量资源,要谨慎使用,否则你的应用可能就此崩溃。

捕捉的功能会促使scroller去重新定义位置,这样可以制作更加花哨的传送带效果。点击这里有个小例子。

默认情况下,Scroller将滚动条分成四分体,或者是相同大小的wrapper。Scroller加入了这个属性允许捕捉scroller里的任何元素,不考虑外部wrapper的大小。如果你想要实现这样的传送带效果,我建议你使用“quadrant”分割。最佳的设置如下:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		snap:true, 
		momentum:false, 
		hScrollbar:false, 
		vScrollbar: false
	});
})

捕获元素,可以通过传递一个字符串来作为查询条件,如下:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		snap:"li", 
		momentum:false, 
		hScrollbar:false, 
		vScrollbar: false
	});
})

在这个例子中scroller可以捕捉到滚动区域中最左上角的li元素

在Scroller这个版本中,可以利用一系列的css来自定义滚动条的呈现。可以给滚动条添加一个class参数,如下:

define(['fui/scroller/1.0'], function(Scroller) {
	var myScroll = new Scroller({
		container: '#wrapper',
		scrollbarClass: "myScrollbar"   // 注意:不是myScrollbarV哦,横向或纵向的scrollbar,Scroller会自动加上后缀
	});
})

你可以点击这里看一个小例子,在这个小例子里,myScrollbarH这个类被添加到了水平滚动条上,myScrollbarV这个类则被添加给了垂直方向上的滚动条上了。需要提醒的是,滚动条是由两个元素组合而成的:容器和显示器。容器同wrapper的高度相同,而显示器则代表的是滚动条本身。

滚动条的HTML结构如下:

<div class="myScrollbarV">
	<div></div>
</div>

.myScrollbarV{
	position:absolute;z-index:100;width:8px;bottom:7px;top:2px;right:1px;
}

.myScrollbarV > div {
	position:absolute;
	z-index:100;
	width:100%;
	/* The following is probably what you want to customize */
	background:-webkit-gradient(linear, 0 0, 100% 0, from(#f00), to(#900));
	border:1px solid #800;
	-webkit-background-clip:padding-box;
	-webkit-box-sizing:border-box;
	-webkit-border-radius:4px;
	-webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
}

Demo如下所示: