H5全屏切换

之前有做过一个微信中的H5小项目,其中有一个交互就是点击完按钮,页面由下往上滑动切换至下一页。做完后发现在Android(华为荣耀5a、华为荣耀3c和OPPO A37m)下效果都还好,但在iphone6s(10.2)中测试时却不尽如人意(条件有限,其它机型未测),可谓一波三折。今天就从头到尾做一次总结记录。

一折

先从最简单的demo开始,主要代码如下:

<div id="wrapper" class="wrapper">
  <div class="page page-one">
    <h1>第一页</h1>
    <a href="javascript:void(0);" class="next-btn">下一页</a>
  </div>
  <div class="hide page page-two">
    <h1>第二页</h1>
    <a href="javascript:void(0);" class="next-btn">下一页</a>
  </div>
  <div class="hide page page-three">
    <h1>第三页</h1>
    <a href="javascript:void(0);" class="next-btn">下一页</a>
  </div>
  <div class="hide page page-four">
    <h1>第四页</h1>
  </div>
</div>

html, body, .wrapper {
  width: 100%;
  height: 100%;
}

.wrapper {
  position: relative;
  max-width: 640px;
  margin: 0 auto;
}

.hide {
  display: none;
}

.page {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
}

.slideUp {
  animation: SlideUp 1s ease;
}

@keyframes SlideUp {
  0% { transform: translate3d(0, 100%, 0) }
  100% { transform: translate3d(0, 0, 0) }
}

var wrapper = $('#wrapper');

var toNextPage = function(e) {

  var curParent = $(e.target).parents('.page');

  setTimeout(function(){
    curParent.addClass('hide');
  }, 1000)

  curParent.next().removeClass('hide').addClass('slideUp');
}

wrapper.on('click', '.next-btn', function(e) {

  toNextPage(e);
})

上述代码我在三个安卓机上测试时都没有问题,但在iOS下却有这样的一个异常,如果用户不小心点击在事件委托的元素"div.wrapper"上而非按钮区域,再点击"下一页"按钮时,下一页就会直接显示出来,而没有从下到上的滑动效果。。

针对这个异常,我也查找了好久原因,很遗憾,,至今没能找到导致这个异常的原因,但找到了两个解决方案:

  • 不采取事件委托,将点击事件直接绑定到a标签上。
  • 引入fastclick库。

修复之后的效果如下:

当引入fastclick解决异常后,我猜想,这个异常会不会是由iOS本身的原生点击事件导致的?如果您知道原因,希望不吝指教,先谢过了!

二折

在解决了上述问题后,接下来为了让按钮看着漂亮一些,我给每一页的翻页a标签加上背景图并去掉文本内容:

<a href="javascript:void(0);" class="next-btn"></a>

.next-btn {
  position: absolute;
  bottom: 20px;
  left: 50%;
  margin-left: -80px;
  
  width: 160px;
  height: 60px;
  text-align: center;
  
  background: url(./../images/btn-start.png) no-repeat;
  background-size: contain;
}

这样改动后,Android下仍没有问题,但iOS下又出现了类似的异常:这次是直接点击按钮后,下一页就会直接显现出来而没有滑动效果。。

在尝试各种解决方法后,无意中发现,在给a标签添加active选择器后,滑动效果正常,而且a标签的交互视觉效果似乎也更好了点。。什么鬼,问题是因此而解决了,但同上,原因还是不明,研究中……

.next-btn:active {
  background-image: url(./../images/btn-start-a.png);
}

效果如下:

三折

页面总算可以一页一页地顺利切换了,下面需要做的是一个转盘抽奖,这里只展示简化部分。

// html
  <div class="turntable">
    ![](./images/turntable.png)
    <div class="lottery_btn">开始抽奖</div>
    <div class="pointer"></div>
  </div>

// css
  .turntable .pointer {
    ...

    -webkit-transition: -webkit-transform 2s ease-out;
    transition: transform 2s ease-out;

    ...
  }
  
// js
wrapper.on('click', '.next-btn', function(e) {

  toNextPage(e)
}).on('click', '.lottery_btn', function(e) {

  var rotate = 'rotate3d(0, 0, 1, ' + (360*4+45) + 'deg)';

  $('.pointer').css({
    '-webkit-transform': rotate,
    'transform': rotate
  })
  // 由于我上面设置的rotate过渡时间是2秒,所以在此处写的是2.2秒后进入抽奖结果页。
  setTimeout(function() {
     toNextPage(e)
  }, 2200)
})

首先我的想法很简单,就是让转盘的指针根据结果在两秒内转动四圈以上最终落在奖品上,与此同时,抽奖结果页再紧接着滑动出来。但结果却还是出乎意料:

转盘指针确实可以正常落在奖品上,但在iOS下只转动了不到半圈。

既然问题出在了转动上,首先想到是不是需要给转动指针的父元素div.turntable添加transform-style以及perspective等属性,但发现添加后还是同样的效果。再联想到可能是rotate3d方法的支持性问题,于是换做rotateZ方法,转动正常。。也就是只做了下面的变动:

var rotate = 'rotateZ(' + degree + 'deg)';

当转盘指针刚停止滚动的时候,在iOS下抽奖结果页直接显现出来,和一二折中遇见的情况很是相似。。

从上面的代码可以看出,我其实是想用setTimeout控制指针旋转动画结束后的下一步动作,问题其实也是出在了这个里面。说白了,如果有一个可以监听动画结束的事件,而将下一步操作放在该事件处理程序中岂不OK?果不其然,当通过监听transitionend事件来处理后,一切正常……

$('.pointer').css({
  '-webkit-transform': rotate,
  'transform': rotate
}).on('transitionend', function() {
  toNextPage(e)
});

小结

其实上面写了这么多,总结起来无非这两个问题:

  • 在iOS下使用transform: rotate3d()制作旋转动画效果时,iOS会以最快捷的路径从起始角度旋转至终止角度,因此旋转角度不会超过180deg。所以如果要连续平滑的从起始角度过渡到终止角度,建议使用rotateX()、rotateY()和rotateZ()代替。
  • 某些情况下(应该不限于上面三种情况),在iOS中将一个元素的display属性从none设置为block后,紧接着为其添加基于transition 和 translate 的动画效果时,动画效果失效。失效原因暂不明确。。继续研究中。

能力和条件有限,总结和测试或许都有很大不足!这是demo地址 ,如果您有什么想法,希望不吝赐教!

最后附上完整效果图:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容