移動端開發HTML5(H5)采用SwiperJS單屏垂直滑動頁面中,某頁内容高度超出螢幕高度解決辦法
當産品給我原型的時候,我覺得這是一個普通的專題,為了趕時間(下班前給的設計稿,産品姐姐說,明早要上!)。當我下班時拿到設計師給出了基于iPhone6分辨率的設計稿時,我陷入了沉思。
不得不說,整體設計十分飽滿,看起來内容很豐富。在750*1334分辨率下的圖檔顯示完美。
然而,不是所有手機看到的都是這個圖的模樣,最重要的是不同浏覽器有不同高度的标題欄,底部有菜單欄,還有甚者,還有虛拟按鍵欄(某些安卓手機例如Meizu MX3)。作為單屏垂直滑動的頁面,如果能完美呈現如此飽滿的内容,并且不會出BUG呢。
廢話少說,目前的狀況就是:這個單屏滑動的頁面中,存在部分slide的内容根本無法一屏剛好顯示完,是以,在這些高度大于浏覽器可視窗高度的slide内,需要一個上下滑動來檢視該slide全部内容。而兩個上下滑動的操作又會産生沖突。對于這個問題該如何解決呢?經過這幾天的研究,我目前得出來了兩個方案。現在來介紹一下:
方案一:在超出可視高度的swiper-slide的内通過設定 allowTouchMove
參數來開啟/禁用滑屏切換的操作
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的另一個官方未有展示的功能~
最後附上demo-2代碼和頁面線上效果
寫在最後
其實,有時候,自己遇到的問題,其實很多人都遇到過,雖然在處理這個問題上,百度的确搜不到相關的資訊,甚至是這樣的問題,我都不知道該如何描述清楚,以便搜尋,所幸google了一下swiper slide content overflow之類關鍵詞查到了SwiperJS作者給出的答案,實在幸運,後來該頁面在優化過程中我重寫用了DEMO-2的方案,心情也是舒暢了許多。
同時,我也查過SF,關于SwiperJS的一些類似的資料,的确也沒有找到,不知道我寫的這個是否能給相關開發的朋友帶來幫助,或者其實大家還有更好的方法,歡迎留言共同學習探讨~