移动前端滑动插件——JRoll面世
又过了一年,终于,第三篇博文要出炉了。
去年9月底,结束创业生涯后,我进入了一家外包公司从事移动前端工作,洽洽这年html5火到要爆,而具备html5技能的工程师却千里难觅,虽然我一直从事PC端的工作,但凭借扎实的js基础,也谋了个中级工程师的职位。多学点东西准没错的。
从事正规的前端工作后,我接触到了underscore、ratchet、backbone、requirejs、seajs、cordova、angular等等一大堆前端框架工具,不禁感慨,原来我以前的圈子是那么的渺小。iscroll,相信大多数移动前端开发者都用过,在我创业那段时间也接触过,由于当时不会用,搁置了。
进入公司后,iscroll便成了不可离开的工具。html5移动应用为了满足业务需求,滑动操作也复杂起来,不再像纯手机网站那样一页下来。而div的overflow:auto属性,在移动设备的表现不太理想,为了解决滑动呆板问题,iscroll似乎成了救星。然而,iscroll并不是万能的,当滑动的元素多起来时,卡顿、闪屏更为严重。为了控制页面元素数量,只好采用增减法,即一次只显示三页,显示第四页时,将第一页删除,始终在屏幕上保持三页的数量,并将位移减去第一页的高度,以保持第二、三页相对屏幕的位置不变。这样一来,iscroll性能方面的缺陷得到了一个比较有效的解决方案。同时,运用空间换性能的方法,将加载过的页面缓存下来,客户体验也是扛扛的。但是,iscroll这就满足了我的需求?如果真是这样的话,就不会有这篇博文了。
为了寻找一个更好的滑动插件,去年12月开始研究IScroll5,今年3月开始着手起草JRoll [ jr: ]。我设计jroll的初衷是为解决iscroll的不足,如此一来,我必须先找出iscroll都有哪些缺陷。
以下是我感觉iscroll需要改进的地方:
1、性能方面,300条数据就会出现卡顿
2、scrollFree参数失效。scrollFree为false时,当左右滑动过程中不能进行上下滑动,上下滑动过程中不允许左右滑动。IScroll5出现的bug是当一开始就斜向滑动的话,scrollFree锁定就会失效。
3、文件太多,iscroll、iscroll-infinite、iscroll-lite、iscroll-probe、iscroll-zoom共五个文件。iscroll是普通版,含滚动条。iscroll-infinite是无限循环版。iscroll-lite是精简版,无滚动条。iscroll-probe是加强版,可监听滑动并添加滑动事件。iscroll-zoom是缩放版。而且这几个文件是不能同时使用的,否则会发生冲突。
4、文件太大,iscroll为了兼容pc,做了很多兼容处理,而且IScroll5里面有很多已经被弃用的代码并没有删除。
5、滑动表单时光标丢失
好,既然问题已经找出来了,那么该如果解决?即便不能解决所有,也应该做到更好。
一、突破性能瓶颈
在研究iscroll源码的过程中,发现造成卡顿的主要原因是使用了css3的transition-duration实现惯性滑动。众所周之,css3动画对设备性能要求比较高,在大面积使用时,对GPU来说更是一项极艰巨的挑战。iscroll做得比较好的是,对于不支持transition-duration的手机使用requestAnimationFrame来补救。目前安卓4.1以上都支持transition-duration,但4.1~4.3性能表现不佳。4.2以上支持requestAnimationFrame,对于不支持requestAnimationFrame的手机可以用setTimeout代替。安卓4.2、4.3虽然支持requestAnimationFrame,但其它性能表现与setTimeout无异。值得高兴的是,现在国内所有手机厂商基本上不再生产安卓4.4以下的手机。按现在的手机更替速度来看,一两年后,html5开发者再也不用为兼容安卓低端机而头疼。
经过测试,使用requestAnimationFrame实现惯性滑动,能滑起上万条数据,虽然在安卓4.4以下效果会打点折扣,但数据多的时候比起transition-duration强多了,在IOS上表现溜溜的。还是苹果牛逼。
权衡取舍,JRoll最终采用requestAnimationFrame来实现惯性滑动。为了降低开发成本及个人精力有限等问题,JRoll只支持webkit和blink内核的浏览器。至于其它内核的浏览器,一来没时间调试,二来穷屌丝没钱买设备(T_T)。
滑动页面的实现原理是在touchmove时移动元素的位置,那到底用absolute好还是用translate好?网上也有不少文章对这两个实现方法的讨论,当然结论也会因系统环境、浏览器内核等因素而异。使用absolute移动位置,可以解决表单丢失光标的问题,但滑动流畅度总是那么的不尽人意。当然在安卓4.1以下系统表现会比translate好些,那此将要被淘汰的系统,我们就不必深究了。使用translate可以开启3D加速,流畅度有了质的提升,只是在软键盘弹出后滑动页面时,某些系统如ios,某些安卓浏览器会出现光标不跟随input输入框的问题,但毕竟这并不影响业务流程的正常操作,况且也很少有人会在软键盘弹出后去滑动页面,因此translate还是比absolute更胜一筹。或许有些同学会问怎样开启3D加速,很简单,要只用到css3任何一个3D属性都会触发硬件加速,例如transform:translateZ(0)。
二、解决scrollFree参数失效
刚刚又看了一下IScroll5的源码,它的选项参数是freeScroll,我把free和scroll的顺序搞反了,糗大了。本来还想着使用和iscroll一样的API,避免打乱用户习惯,现在JRoll已经上线了,改回来不太好,将错就错吧。iscroll的freeScroll实现方法是先滑动再判断要锁定哪个方向,这种做法导致的问题就是在斜向滑动时判断失效。这里,额外补充一个小知识,preventDefault阻止浏览器默认行为这个属性在滑动过程中才设置是不会生效的。例如,你想在横向滑动时将preventDefault设为true,可以通过e.pageX和e.pageY的差值比较判断正在进行横向滑动还是竖向滑动抑或是斜向滑动,当然一般很少判断斜向滑动,pageX的差值比pageY的差值大时都当作是横向滑动。此时,如果你先竖向滑动,滑动已经开始,然后再横向滑动,preventDefault并不会起作用。jroll修正freeScroll的方法是先判断要锁定哪个方向再执行滑动。简单点说,就是touchmove的第一个移动位置不会使页面滑动,而是用于判断将要进行的方向,第二个移动位置才开始滑动页面。
三、去繁从简
iscroll将各项功能都拆分成单个文件,每个文件又不能一起使用,在一个项目既用到zoom又用到probe的话确实很让人头疼。jroll使用一个文件实现了滚动条、缩放、事件监听等功能,开发者可不必再为到底使用哪个文件而手足无措。至于无限循环这个功能,将会做成jroll的插件。同时,基于jroll滑动的插件,如日期控件、日历控件、分页等等鄙人也在谋划中,完成之后,html5开发的应用可不必使用input[type=date]来调用原生日期组件,直接调用jroll的日期插件可做到所有移动终端对于日期控件这块体验一致,敬请期待。
四、专注移动
iscroll为了兼容各种终端,而且升级后废弃的代码也没有删除,因此文件越来越庞大,这并不利用移动应用的开发。jroll一个崭新的产品,没有历史遗留问题,而且专注于移动应用开发,代码相当精简,源文件24k,经过UglifyJS压缩后才12k。当然也使用了mousemove、mousewheel等兼容谷歌浏览器非移动模拟器模式,这也是为了方便开发调试,占用的代码量很少。jroll没有像iscroll那样在touchstart时preventDefault,因此不需要click:true来允许点击a链接。jroll在安卓方面做了自动定位表单的优化,即是点击input时可自动将input定位到可见位置不会被软键盘遮挡,ios会自动定位不需要我们多此一举去优化。
好了,说了这么多,让大家一起来领略一下jroll。
jroll有五种引入方式:普通引入、CommonJS规范引入、RequireJS规范引入、SeaJS规范引入和强制普通方式引入。
使用时也是像iscroll那样new一个。jroll = new JRoll("#wrapper", {bounce:true, zoom:true, ...})。
可选项一览表:
可选值 | 默认值 | 说明 |
---|---|---|
scroll | true | 使能滑动 |
scrollX | true | 使能横向滑动 |
scrollY | true | 使能竖向滑动 |
scrollFree | false | 使能自由滑动,默认情况下,x方向在滑动时,y方向不能滑动,相反亦然,如果应用于对图片进行放大滑动,可将此参数设为true,如果此参数设为true,请务必将bounce设为false,否则将影响滑动效果 |
zoom | false | 使能缩放 |
zoomMin | 1 | 最小缩放倍数 |
zoomMax | 4 | 最大缩放倍数 |
bounce | false | 使能回弹 |
scrollBarX | false | 开启x滚动条,若将此参数设为字符串,例scrollBarX:‘custom‘,可对滚动条样式进行自定义 |
scrollBarY | false | 开启y滚动条,与scrollBarX类似用法 |
scrollBarFade | false | 开启滚动条的渐隐模式 |
stopPropagation | false | 禁止事件冒泡 |
preventDefault | true | 禁止touchmove默认事件,默认为true,当preventDefault为false时有可能触发浏览器自带的左右滑动切换页面功能,而且像QQ手机浏览器(Android4.2)会出现无法滑动的奇葩现象,因此本站不建议将preventDefault设为false。 |
momentum | true | 滚动平滑过渡,如果设为false,手指释放后将马上停止滑动 |
autoStyle | true | 为wrapper 和scroller(wrapper 的第一个子元素)添加样式,默认如果wrapper 的position为static,将被修改成relative,并将overflow设为hidden,scroller 的min-height设为100% |
g | 0.0008 | 模拟重力加速度,g值越小,运动时间越长 |
adjustTop | 190 | 安卓手机输入表单时自动调整输入框位置,默认190,表示输入框距离顶部190px |
scroller | wrapper的第一个子元素 | 指定scroller,不可动态更改,可以是id选择器字符串#scroller ,也可以是dom对象document.getElementById(‘scroller‘) |
两个常用方法:refresh和scrollTo。
能看到这里,说明你很有毅力,若要更详细的了解jroll,可访问JRoll,现已开源到oschina,源码地址:https://git.oschina.net/chenjianlong/JRoll
ps:一眨眼一年过去了,去年给客户做的作品现在已经访问不到了,唉,有时不得不感慨,现在的人肿么都那么浮躁,说好要做品牌的,结果才一年,客户就把网站关掉了。不过请大家放心,jroll是放在我自己的服务器上的,绝对不会那么轻易闭站。只是穷屌丝只买得起阿里云550元每年的产品,访问量多了可能会挤爆,没关系,还可以到开源中国去下载源码或在51cto本博客留言问我拿。
本文出自 “终天霸主” 博客,请务必保留此出处http://barzu.blog.51cto.com/3026668/1696321