在微信的文檔中有一個章節說明了『 原生組件的使用限制 』有這麼一段話html
『因爲原生組件脫離在 WebView 渲染流程外,所以在使用時有如下限制: 原生組件的層級是最高的,因此頁面中的其餘組件不管設置 z-index 爲多少,都沒法蓋在原生組件上。 後插入的原生組件能夠覆蓋以前的原生組件。 原生組件還沒法在 scroll-view、swiper、picker-view、movable-view 中使用。 部分CSS樣式沒法應用於原生組件,例如: 沒法對原生組件設置 CSS 動畫 沒法定義原生組件爲 position: fixed 不能在父級節點使用 overflow: hidden 來裁剪原生組件的顯示區域 原生組件的事件監聽不能使用 bind:eventname 的寫法,只支持 bindeventname。原生組件也不支持 catch 和 capture 的事件綁定方式 在iOS下,原生組件暫時不支持觸摸相關事件。 在工具上,原生組件是用web組件模擬的,所以不少狀況並不能很好的還原真機的表現,建議開發者在使用到原生組件時儘可能在真機上進行調試。』
所謂的原生組件,即非Web組件系統擴展Native組件。由於小程序在視圖渲染層面使用了WebView,而在Video,Map這類組件,使用WebView的WebCore渲染以後體驗不佳的詬病一直存在,並且標準不一。小程序上因使用原生的WebView進行渲染,而不是用修改的WebView內核(至少在iOS上沒有這麼幹),而沒法對web原生標籤擴展。基於用戶體驗,和坑爹的技術限制,小程序提出了原生組件的概念,也就是在WebView上面使用原生組件填充佔位元素的方式修補這類組件用戶體驗問題。由於WebView和原生組件在應用層自己就不是一個渲染層級,因而出現Web上面的標籤沒法浮於Video之上(直播應用的惡夢),在不修改技術思路的前提下,position: fixed, overflow: hidden這樣的屬性是不可能用於原生組件的樣式的。不過僞同層渲染也不是說不可能,即在渲染原生組件時候根據層級鏤空面積。web
特別在Map上使用WebView做爲渲染以後體驗不佳的詬病一直存在,特別是地圖上marker標記過多的重度場景下,筆者所在的公司的在使用高德地圖Web端提供出來的C端具有反人類的體驗,地圖拖拉龜速,點擊響應緩慢,加載loading地圖區域等待時間過長。而Video則支持的格式有限,列出部分瀏覽器的支持的以下:小程序
Firefox:支持 Ogg Vorbis和WAV Opera :支持Ogg Vorbis和WAV Safari :支持MP3,AAC格式 ,和MP4 Chrome :支持Ogg Vorbis,MP3,WAV,AAC和MP4 Internet Explorer 9+ :支持MP3,AAC格式 ,和MP4 IOS :支持MP3,AAC格式 ,和MP4 Android :支持AAC和MP3
上述,能夠知道視頻支持有限(限於版權)。而就咱們關注的移動端iOS和Andoroid,實現一個視頻播放,咱們可能都會有如下幾點的需求:
一、全屏處理;
二、覆蓋層效果;
三、自動播放;
四、播放控制;
五、隱藏播放控件;
在iOS上若是使用WebView,你沒法修改全屏下的工具這一點體驗已經足夠讓全部的產品經理抓狂,更不用說Android的這麼多的機型。覆蓋層效果在微信上不得不使用微信提供原生組件cover-view實現,而限於原生實現限制,cover-view的支持有限。微信小程序
這也應該是微信小程序團隊現階段使用的方案,經過特殊的佔位標籤,使用getBoundingClientRect獲取組件位置,而原生組件跟隨Webview滾動。
Talking is cheap. Show me your code,那麼用代碼實現的效果的以下。
從圖中可見,覆蓋層確實位於原生組件之下。瀏覽器
此方式略微複雜。須要經過與Webview scroll聯動的置於Webview之下的Component Layer實現,而Webview背景設置爲透明。至於事件,經過Webview的事件透傳,傳遞到Component Layer,須要經過緩存webview中元素再計算是否被點中經過重寫hitTest方法實現。經過此技術方案實現的好處也是明顯的,由於原生組件層不少時候都是置於最底層,而Web上的組件能夠輕鬆覆蓋於Native之上,無需使用cover-view之類的hack方法。
效果以下所示緩存
在iOS上還特別須要注意一點UIWebview的坑。在使用-webkit-overflow-scrolling 使用,你會發現momentum scroll階段並不會觸發scroll事件,並且 scrollTop 屬性不會變化,固然getBoundingClientRect也一樣失效。若是考慮使用touchmove 這樣事件你也僅僅在手指還在屏幕上的時候觸發,檢測滾動區域內部元素的getBoundingClientRect 一樣無效。微信
固然幸運的是,這麼大一個坑只是發生在UIWebview,對WKWebview並無影響。ide