by addy 原创文章,欢迎转载,但希望全文转载,注明本文地址。

本文地址:https://www.iamaddy.net/2016/11/h5-iphone-two-pages/

背景

feeds流在横屏下的体验非常糟糕,内容可视区域小,内容被拉长,导致用户体验很差。

h5实现iPhone横屏下的双页模式

后来看到ipad和大屏的iPhone手机在横屏下的视觉,觉得如果网页做成这样的估计效果会好很多。

h5实现iPhone横屏下的双页模式

实现后的效果可以看下面的小视频:

实现

在实现上述的功能,需要注意的地方还有很多,首先来跟大家大概讲下交互的逻辑。

h5实现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平台下,首页看帖,用户点击帖子次数,是之前的三倍有余。
h5实现iPhone横屏下的双页模式

本文为原创文章,可能会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,谢谢合作

本文地址:https://www.iamaddy.net/2016/11/h5-iphone-two-pages/

个人知乎,欢迎关注:https://www.zhihu.com/people/iamaddy

欢迎关注公众号【入门游戏开发】 入门游戏开发