之前有做過一個微信中的H5小項目,其中有一個交互就是點擊完按鈕,頁面由下往上滑動切換至下一頁。做完后發(fā)現(xiàn)在Android(華為榮耀5a、華為榮耀3c和OPPO A37m)下效果都還好,但在iphone6s(10.2)中測試時卻不盡如人意(條件有限,其它機型未測),可謂一波三折。今天就從頭到尾做一次總結(jié)記錄。
一折
先從最簡單的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"上而非按鈕區(qū)域,再點擊"下一頁"按鈕時,下一頁就會直接顯示出來,而沒有從下到上的滑動效果。。

針對這個異常,我也查找了好久原因,很遺憾,,至今沒能找到導致這個異常的原因,但找到了兩個解決方案:
- 不采取事件委托,將點擊事件直接綁定到a標簽上。
- 引入fastclick庫。
修復之后的效果如下:

當引入fastclick解決異常后,我猜想,這個異常會不會是由iOS本身的原生點擊事件導致的?如果您知道原因,希望不吝指教,先謝過了!
二折
在解決了上述問題后,接下來為了讓按鈕看著漂亮一些,我給每一頁的翻頁a標簽加上背景圖并去掉文本內(nèi)容:
<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下又出現(xiàn)了類似的異常:這次是直接點擊按鈕后,下一頁就會直接顯現(xiàn)出來而沒有滑動效果。。

在嘗試各種解決方法后,無意中發(fā)現(xiàn),在給a標簽添加active選擇器后,滑動效果正常,而且a標簽的交互視覺效果似乎也更好了點。。什么鬼,問題是因此而解決了,但同上,原因還是不明,研究中……
.next-btn:active {
background-image: url(./../images/btn-start-a.png);
}
效果如下:

三折
頁面總算可以一頁一頁地順利切換了,下面需要做的是一個轉(zhuǎn)盤抽獎,這里只展示簡化部分。
// html
<div class="turntable">

<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
})
// 由于我上面設(shè)置的rotate過渡時間是2秒,所以在此處寫的是2.2秒后進入抽獎結(jié)果頁。
setTimeout(function() {
toNextPage(e)
}, 2200)
})
首先我的想法很簡單,就是讓轉(zhuǎn)盤的指針根據(jù)結(jié)果在兩秒內(nèi)轉(zhuǎn)動四圈以上最終落在獎品上,與此同時,抽獎結(jié)果頁再緊接著滑動出來。但結(jié)果卻還是出乎意料:

轉(zhuǎn)盤指針確實可以正常落在獎品上,但在iOS下只轉(zhuǎn)動了不到半圈。
既然問題出在了轉(zhuǎn)動上,首先想到是不是需要給轉(zhuǎn)動指針的父元素div.turntable添加transform-style以及perspective等屬性,但發(fā)現(xiàn)添加后還是同樣的效果。再聯(lián)想到可能是rotate3d方法的支持性問題,于是換做rotateZ方法,轉(zhuǎn)動正常。。也就是只做了下面的變動:
var rotate = 'rotateZ(' + degree + 'deg)';
當轉(zhuǎn)盤指針剛停止?jié)L動的時候,在iOS下抽獎結(jié)果頁直接顯現(xiàn)出來,和一二折中遇見的情況很是相似。。
從上面的代碼可以看出,我其實是想用setTimeout控制指針旋轉(zhuǎn)動畫結(jié)束后的下一步動作,問題其實也是出在了這個里面。說白了,如果有一個可以監(jiān)聽動畫結(jié)束的事件,而將下一步操作放在該事件處理程序中豈不OK?果不其然,當通過監(jiān)聽transitionend事件來處理后,一切正常……
$('.pointer').css({
'-webkit-transform': rotate,
'transform': rotate
}).on('transitionend', function() {
toNextPage(e)
});

小結(jié)
其實上面寫了這么多,總結(jié)起來無非這兩個問題:
- 在iOS下使用transform: rotate3d()制作旋轉(zhuǎn)動畫效果時,iOS會以最快捷的路徑從起始角度旋轉(zhuǎn)至終止角度,因此旋轉(zhuǎn)角度不會超過180deg。所以如果要連續(xù)平滑的從起始角度過渡到終止角度,建議使用rotateX()、rotateY()和rotateZ()代替。
- 某些情況下(應(yīng)該不限于上面三種情況),在iOS中將一個元素的display屬性從none設(shè)置為block后,緊接著為其添加基于transition 和 translate 的動畫效果時,動畫效果失效。失效原因暫不明確。。繼續(xù)研究中。
能力和條件有限,總結(jié)和測試或許都有很大不足!這是demo地址 ,如果您有什么想法,希望不吝賜教!
最后附上完整效果圖:
