h5实现iPhone横屏下的双页模式
by addy 原创文章,欢迎转载,但希望全文转载,注明本文地址。
背景
feeds流在横屏下的体验非常糟糕,内容可视区域小,内容被拉长,导致用户体验很差。
后来看到ipad和大屏的iPhone手机在横屏下的视觉,觉得如果网页做成这样的估计效果会好很多。
实现后的效果可以看下面的小视频:
实现
在实现上述的功能,需要注意的地方还有很多,首先来跟大家大概讲下交互的逻辑。
需要注意的几个点是:
1、横竖屏旋转切换时的逻辑 2、导航条返回逻辑
用户打开网页是竖屏,那只展示左侧的feeds流列表,点击浏览帖子,只展示右边详情页面。通过浏览器导航返回时,回到左侧列表。
用户打开网页是横屏,同时展示两个页面,点击浏览帖子,右侧显示详情页面,不记录浏览历史,导航条返回无效。
横屏时转竖屏,看用户最后在左侧还是右侧滑动来决定展示哪一侧。但如果是旋转后显示右侧,一定要对改变浏览器的历史,否则这时候导航条返回按钮将返回不到列表。
竖屏转横屏时,无论是在左侧还是右侧,左右侧都显示。
旋转屏的判断接口:
switch(window.orientation){
case 0:
case 180:
// todo
break;
case -90:
case 90:
// todo
break;
}
window.onorientationchange = orientationChange;
当然如果onorientationchange
不支持,只能监听window.onresize
接口,通过window的宽高比来判断当前横竖屏状态。
好了,现在从最开始来讲解下实现过程。
1、方案选型
有很多种实现方案:
1、所有逻辑都在一个html页面来实现。可以理解为一个单页应用。 2、分为两个页面,右侧详情页为iframe。 3、分为三个页面,frameset包含左右两个frame,地址为各自页面。
最理想的是1,因为iframe在网页开发中的诟病太多,尤其是mask浏览器(做过msdk开发的应该更加清楚痛苦)。但是详情页的功能逻辑异常的多,两个页面柔和在一起做,在现有的框架下,是一件吃力不讨好的事情。要做,时间上不允许,短短一个星期就要上线。
所以只能是2和3,3呢,其实和2区别也并不太大,只是多了个frame,但是frameset这玩意儿在pc端可以玩的很转,iOS就不太友好了,官方明确说明,最好放弃使用。所以只能pass了。
只剩下2了,iframe。为啥不用两个,iframe对性能方面本身就不友好,能少用就尽量少用。列表页功能相对简单,模块可复用度高,详情页改造比较少,只要稍微改变样式就行。所以这是目前最优。
1、双侧布局
<div class="game-post game-post_index game-post_hengpin ui-flex" id="panel-control">
<div class="game-post__left"></div>
<div class="game-post__right">
<iframe frameborder="0" id="detail-iframe" src="url"></iframe>
</div>
</div>
最外层的div作为最大的容器,通过class来控制左右div的显隐。
左右两侧的内容高度是不一致的,要体验上OK,左右容器是固定为屏幕高度,所以必须要做局部区域滚动。
.game-post__left {
width: 14.5rem;
height: 100%;
-webkit-overflow-scrolling: touch;
overflow-y: scroll;
border-right: 1px solid #e1e1e1;
}
.game-post__right {
-webkit-overflow-scrolling: touch;
overflow-y: scroll;
height: 100%;
}
iframe{
width: 100%;
height: 100%;
}
-webkit-overflow-scrolling: touch;
必须要加,不加ios下就滑动不了了。
左侧宽度固定,右侧根据屏幕宽度自适应,由JavaScript计算。iframe负责把右侧铺满就行。
2、浏览器history
这里的一个重点就是history,由于在点击列表页查看详情页面时,只需要设置iframe新的地址就好,至于要不要留下访问历史,看产品需求。
location.href =xxxx
location.replace(xxxx)
还有就是从双页面旋转到详情页,这时候需要追加一个历史,以供返回到列表页:
switch(window.orientation){
case 0:
case 180:
if(window.__lastTouch === 'detail' ){
var stateObj = {page: 'list'};
history.pushState(stateObj, '', "");
rightPanel.style.width = '100%';
......
}
}
// 点击导航的返回按钮就执行下面逻辑,回到列表页面。
window.onpopstate = function(e){
var clientWidth = document.body.clientWidth;
var clientHeight = document.body.clientHeight;
if(clientWidth < clientHeight) {
showRight()
}else{
....
}
};
onpopstate在移动端基本都覆盖了,可以放心大胆的使用。如果要考虑兼容,追加URL的hash。
至于旋转的时候要显示哪个,用标记为解决就好,在两个页面都监听touchmove事件
// window.__lastTouch : list | detail
document.addEventListener('touchmove', function(){
top.window.__lastTouch = 'xxxx'
});
3、其他改造
图片懒加载,滚动加载数据,依赖scroll的逻辑都需要监听到新的元素上。基本无太大改动。
4、意外惊喜
看两个视频对比下就知道了。msdk浏览器是没有新打开webview的api,只能当前页面location跳转,而我们的列表首页是动态ajax翻页的,一旦用户滚动到下一页看帖再返回的时候,由于不能记录历史位置,所以又是从第一个开始,真是想骂娘。
旧:
新:
5、结果
以数据说话,iPhone平台下,首页看帖,用户点击帖子次数,是之前的三倍有余。
本文为原创文章,可能会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,谢谢合作
个人知乎,欢迎关注:https://www.zhihu.com/people/iamaddy
欢迎关注公众号【入门游戏开发】
近期评论