移动端开发HTML5(H5)采用SwiperJS单屏垂直滑动页面中,某页内容高度超出屏幕高度解决办法
当产品给我原型的时候,我觉得这是一个普通的专题,为了赶时间(下班前给的设计稿,产品姐姐说,明早要上!)。当我下班时拿到设计师给出了基于iPhone6分辨率的设计稿时,我陷入了沉思。
不得不说,整体设计十分饱满,看起来内容很丰富。在750*1334分辨率下的图片显示完美。
然而,不是所有手机看到的都是这个图的模样,最重要的是不同浏览器有不同高度的标题栏,底部有菜单栏,还有甚者,还有虚拟按键栏(某些安卓手机例如Meizu MX3)。作为单屏垂直滑动的页面,如果能完美呈现如此饱满的内容,并且不会出BUG呢。
废话少说,目前的状况就是:这个单屏滑动的页面中,存在部分slide的内容根本无法一屏刚好显示完,因此,在这些高度大于浏览器可视窗高度的slide内,需要一个上下滑动来查看该slide全部内容。而两个上下滑动的操作又会产生冲突。对于这个问题该如何解决呢?经过这几天的研究,我目前得出来了两个方案。现在来介绍一下:
方案一:在超出可视高度的swiper-slide的内通过设置allowTouchMove
参数来开启/禁用滑屏切换的操作
该方案内容较长,废话较多,是个人尝试解决问题的一点心得,若无兴趣可直接看方案二
开发流程和思考:
首先建议下载demo-1在本地,通过Chrome手机模拟或者手机(手机预览需要自行开本地服务器)运行一下看看效果,体验一下实际使用感受和觉得有哪些问题。
由于整个页面仅花了几个小时完成,大部分时间用于阅读swiperjs官方文档解决该问题,因此页面代码相对混乱,并且方案一并非最优化方案,因此不再优化。其实也因为对于swiperjs的API不够熟悉,所以写了很多不太优化的冗余代码,所以DEMO-1主要介绍我的一些开发过程中勉强实现效果的想法。
前奏:
坑爹的设计啊,又不是人人都是iPhone6!T_T。设计稿单屏显示效果好,时间不够设计是不可能改了,找产品聊天,说,既然都单屏滑动,这个设计内容太饱和,我压缩一下,尽量大部分设备能显示完整内容区域,产品不同意。可是苦了我这个小前端。口头上对产品说,那你找个内容超出屏幕高度的实例我看看,我都没见过!心里还是软软的,要不试试吧,说不定很容易呢。
开发ing:
先按照SwiperJs的DEMO搭好页面,做好样式。反正赶时间,全部切整图,细节不管了。很快页面雏形有了。此刻没有开始的loading的。
接下来做滑动,很显然,的确按照设计稿一屏根本显示不完,加上该死的各种状态栏占用的高度,实际可视区域很小。然而怎么获取到每屏内部的高度呢,有些屏是整张背景图,是没有高度的,这种,好说,我直接写高宽最小100%。有的有内容,但是如何检测到呢,首先每个slide里面都要有一个wrap,我这里用的类名page,所有样式都是基于page来的,然后页面加载的时候,在底部创建了个临时的div,遍历有几个slide,每次都将slide写入临时div,然后获取到真实高度,再添加一个realheight属性给对应的slide,遍历结束后清除临时div,这样每个slide的真实高度就有了。
接下来,每次滑倒对应的slide的时候,开始检测它的内容高度realheight,是否超出了可视区高度,如果超出,我就阻止了allowTouchMove
,如下:
mySwiper.allowTouchMove = false;
这下可以内部滚动了,但是到了底我要滑到下一屏咋办,要释放allowTouchMove,于是又在这里加了一个滚动监听事件,当滚到底部时,设置为true,当然同样到滑倒顶部也要设置true,以便返回上一屏,止于此处的具体优化就不多说了。原理大概就是这样~
似乎都调试好了,其实还有个隐藏的问题,就是我这个页面的图片较多,网速较差的情况下,图片未能加载完,真实高度是无法获取到的。于是又要想办法弄了一个图片加载结束后才开始执行其他脚本。这里赶时间也就随便找了一段抄过来了,还挺好用。抄自Can I sync up multiple image onload calls?,顺便又加了个简单的loading页面。反复测试了几次,看起来勉强还是可以的,于是找产品聊了聊,好在基本上过了。
总结:
虽说,其实代码方面有很多问题,但是有时候工作上速度比质量更重要,也就先这样上线了~同样的我在上线后有了时间的情况下,继续寻求更佳的解决办法,于是才找到方案二~
方案二:作者给出的完美方案(4.x测试通过 )
通过监听swiperjs内部的touchstart
和touchmove
获取到手指滑动的垂直高度差,判断滑动手势的方向,并获取slide.scrollHeight
和slide.offsetHeight
值(也就是DEMO-1中的获取页面可视区域高度的方法。),以便得到正确的是否为内部滚动检测。如果是,则阻止touchmove
事件,我当时完全不知道这个阻止了就能阻止切屏了。
当然,css对应的也要写好。
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide {
background: #f1f1f1;
color: #000;
text-align: center;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
其实看一下源码就很清楚了。在目前,我未发现任何BUG。也算是完美了SwiperJS的另一个官方未有展示的功能~
写在最后
其实,有时候,自己遇到的问题,其实很多人都遇到过,虽然在处理这个问题上,百度的确搜不到相关的信息,甚至是这样的问题,我都不知道该如何描述清楚,以便搜索,所幸google了一下swiper slide content overflow之类关键词查到了SwiperJS作者给出的答案,实在幸运,后来该页面在优化过程中我重写用了DEMO-2的方案,心情也是舒畅了许多。
同时,我也查过SF,关于SwiperJS的一些类似的资料,的确也没有找到,不知道我写的这个是否能给相关开发的朋友带来帮助,或者其实大家还有更好的方法,欢迎留言共同学习探讨~