DCloud_heavensoft
DCloud_heavensoft
  • 发布:2014-06-30 05:42
  • 更新:2020-01-20 14:57
  • 阅读:99992

提升HTML5的性能体验系列之二 列表流畅滑动

分类:HTML5+

本系列文章是针对5+App的,与uni-app无关

系列文章目录导航:

App的顶部一般有titlebar,下面是list。
常见的一个需求是要在list滚动时,titlebar不动。
这个简单的需求,但在HTML世界里实现起来其实并不简单。因为普通的HTML方式做不到60fps的无掉帧平滑滚动。

在pc web上的做法是使用div的区域滚动,把list放到div里。
但div滚动条在Android4.4以下的手机上不可商用,如果dom复杂,不管多高端的Android手机,滚动效果也惨不忍睹。

还有一种做法是把titlebar使用fix来固顶。
但此时手机浏览器的滚动条会通到顶部,当titlebar的右侧出现滚动条时,看起来非常怪异。
还有一个副作用是滚动太快时,titlebar的div会下来一下又弹上去。这是因为滚动时触发页面重绘,dom很复杂时重绘来不及,绝对定位的titlebar就会先下来后上去。

还有一种方法是使用自绘的滚动条,即不用浏览器的滚动条,自己画一个滚动条,iScroll等方案是采取这种思路。但模拟的始终是模拟的,和原生的滚动条效果还是差很多,在列表头和尾的拉动回弹的表现不佳,而且列表长了、内容复杂了,非常卡顿。

想要解决这个问题其实也不难,既然div的滚动条卡,而浏览器body的整体滚动条不卡,那就老老实实使用浏览器的body滚动。至于title区域的滚动条通顶和固定方案,使用原生title来解决。
HBuilder8.0起,支持了原生的titleNView,创建webview对象时,在style参数里配置titleNView就可以在Webview上加一个原生的title。

plus.webview.create('new.html', 'new', {'titleNView':{'backgroundcolor':'#FFFFFF','titletext':'标题栏','titlecolor':'#FF0000'}});

HTML页面的滚动部分会自动在这个原生title下面。

titleNView的具体api见,功能还是比较丰富的:http://html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewTitleNViewStyles
titleNView属于Webview的style,自然也可以通过Webview的setstyle方法来修改titleNView的参数,比如用js动态修改titleNView上的文字,可以使用setstyle方法给titleNView重新配置参数即可。修改是增量的,不是全量重写。

提到原生封装的title,人们的直觉一般是自定义性差。
但其实不然,DCloud始终重视开发者的自定义性。
titleNView的父类是plus.nativeObj.view,这是一块原生画布,可以自由的在上面写字绘图、设编辑框,拥有良好的自定义性。
通过Webview的getTitleNView()方法,可以得到标题栏的NView对象,然后参考nview的api,自由定制界面。http://html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View

当然90%的使用场景,在titleNView自带的封装参数里就能完成。个别情况下开发者才需要研究nview的api手绘界面。

配合nativeObj下面的原生imageslider,还可以实现沉浸式题图效果,题图开始通顶到状态栏上,在向下滚动后渐变消失,而title渐变出现,非常动感。
关于沉浸式,是另外的话题,此处不展开。有兴趣可参考http://ask.dcloud.net.cn/article/1150

使用titleNView还有一个好处,在新窗体动画时,不管内容页面渲染多么慢,原生title在动画期间一定是渲染好的,这样页面不会整屏白屏。

mui对这个效果进行了封装,使用mui.openWindowWithTitle即可打开一个带原生头的webview。
在Hello mui里nav bar中点“native title”,可看到效果和源码。

已过期历史:在HBuilder8.0以前,官方曾推荐过双Webview式title。
即把屏幕切分成2个webview,把titlebar的HTML装载到一个webview里,list页面是另一个webview,list页面直接使用浏览器的滚动条而不是div滚动条,这样也可以得到一个流畅的列表滑动体验。
在mui框架里,通过mui的init里的subpage,可以通过配置而不是编码的方式更加简单的开发这种双webview界面。
但在nview成熟后,官方已经废弃了双Webview模式。目前是不再主推双Webview,但开发者的老代码仍然可以兼容。

关于bounce回弹效果
HTML5+提供了原生的bounce回弹效果,默认是开启的。
但也可以关闭和进行参数设置,具体见http://html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewBounceStyle

如果你的App滚动不流畅,可能的原因:

  1. 有人仍然使用div滚动然后抱怨滚动不流畅,注意检查自己的代码,一定要用body滚动而不是div滚动。
    mui为了多端发布兼容和部分选择器项目滚动,是提供了div滚动的,尤其是在iOS上因为性能较高使用面更大,但这些都是可配置的,觉得不流畅时注意检查配置是不是变成div滚动了。
  2. 不管是mui提供的div滚动还是plus.webview的body滚动,都是可以设滚动加速度值的,可以根据自己的页面情况设置不同的加速度值。默认其实不用设置,但如果你设置了错误的值,请检查并修复。
  3. 你可能关闭了硬件加速。Android上如果不开启硬件加速,很难做到60fps的平滑滚动。具体参考Android硬件加速详解
  4. 可能是因为js监听了滚动。js监听滚动,并实时计算和修改dom,会导致卡顿。如果你需要做下拉到底自动翻下一页,那么只需要监听HTML5+提供的页面到底事件,而不是任意滚动事件都监听。具体参考提升HTML5的性能体验系列之三 流畅下拉刷新
16 关注 分享
wglhtml5 hellojh 海洋 仙人指路 大鱼泡泡 igo44444 dreamboycx 你猜我猜不猜 最爱橙子 Android_XR 9***@qq.com 可苦可乐 9***@qq.com 2***@qq.com 1***@qq.com w***@qq.com

要回复文章请先登录注册

落花时节

落花时节

不太好 body滚动只能滚动一个地方。。
2020-01-20 14:57
1***@qq.com

1***@qq.com

div 原生滚动条在移动端一点也不卡, 内容再多也表现完美
反倒是模拟滚动条, 内容一多就卡
演示地址
http://www.mu78.com/scroll-demo/index.html

代码地址
https://gitlab.com/ni5802372/vue-better-scroll-demo.git
2019-03-18 14:06
DCloud_heavensoft

DCloud_heavensoft (作者)

回复 biubiu灬 :
http://ask.dcloud.net.cn/article/141
2018-07-19 09:47
biubiu灬

biubiu灬

回复 DCloud_heavensoft :
我放在body里滚动了,但是下拉刷新显示不出来
2018-07-19 08:30
蔡邵鑫

蔡邵鑫

回复 DCloud_heavensoft :
body中height:100%,滑动会与下拉刷新冲突
http://ask.dcloud.net.cn/question/44422
2017-12-20 13:48
GraceUI

GraceUI

沉浸式、mui、h5+ 视频教程:
http://www.hcoder.net/course/index/cate/4
2017-07-06 09:27
小虎虎

小虎虎

回复 DCloud_heavensoft :
Android 初始化的时候子页面打开下拉刷新和上拉加载功能。下拉时有回弹效果,可是上拉的时候是没有回弹效果的。
还有一个问题是,为什么把子页面的bounce打开后,Android并无bounce效果
2016-12-16 11:06
DCloud_heavensoft

DCloud_heavensoft (作者)

js不要检测滑动,Android浏览器默认的上下滚动没有故障,我们的这个方案也不会干涉新的斜上滑动问题。
2014-10-27 17:14
musiclee

musiclee

试过发现这种方式在iphone4上面滑动是比较流畅的,但是在android下面有个问题,就是手指如果是斜着上下滑动,那么经常滑不起,只能是比较严格的上下滑动没问题,这个怎么解决?在plus里面有没有配置一类的方式来放宽对滑动的检测条件?
2014-10-27 10:35
半杯可乐

半杯可乐

可以卸载框架中,写一个方法将窗体分为三部分,head,body,footer。将head做为主窗体,加载content(也就是body部分),head和footer是兄弟窗口,均在body上方。
函数:
function con(id,url,x,y)
用于根据一个DOM元素的高宽创建一个浮动窗口。
参数:
id为DOM元素的名字,同时也会是浮动窗口的名字
url为浮动窗口加载的页面
x为浮动窗口加载时的X坐标
y为浮动窗口加载时的y坐标

浮动窗口的高宽与id所指定的DOM元素的高宽相同。
2014-09-26 09:15