video 標籤沉浸式播放解決方案
“沉浸播放式”這個概念是我從Android開發裏面的沉浸式引申過來的一個概念,沉浸式其實就是隱藏頁面頂部的status bar和底部的navigation bar之後呈現出來的頁面,一般用戶很容易把沉浸式狀態欄和透明化狀態欄混爲一談,他們的區別如下:
沉浸式狀態欄
透明化狀態欄
那麼回到前端開發,讓我們看一下如何讓video標籤呈現這種沉浸式的播放效果,平常我們使用video標籤都是這樣的:
正常情況下我們要做豎版視頻,視頻的比例都是16:9,也就是高/寬約等於1.78,這裏用到的測試視頻也是16:9的,而且默認情況下video的object-fit屬性的值是contain,也就是保持長寬比,我們先看下不做處理在iphone6/7/8下的表現情況:
在iphone6/7/8下的表現情況
看起來比較完美,因爲這幾款手機分辨率都是16:9的,視頻維持屏幕大小完全沒有問題,接下來看一下分辨率不是16:9的機型,比較典型的就是iphoneX,面向老闆開發的同學可能對適配這款機型頗有怨言:
iphoneX下的表現情況
有人會覺得奇怪爲什麼我們設置了video的寬高都是百分百上下還漏出了兩個白條,這裏其實是object-fit這個屬性在作怪,既然默認的是contain,我們就改爲fill吧,再看一下效果:
object-fit:fill
這樣看起來沒問題,但是你覺得產品小姐姐會這麼輕易放過你嗎?too navie,你看我們正常16:9的視頻在iphoneX這種18:9的屏幕上是有形變的,而且市面上這麼多分辨率不同的設備,如果要追求不同的手機上有最接近的用戶體驗這麼做肯定是不行的,有人可能會提到object-fit中的cover屬性,沒錯,這個屬性可以讓我們的視頻等比例縮放,如果寬高不匹配會對處理對象做裁剪操作,來我們看一下現在在微信裏面的效果:
微信裏的效果
其他效果都蠻好,你會發現右上角有個可惡的全屏,這個全屏按鈕是微信的x5內核自帶的,沒法去除,這個有很多人給騰訊x5開發團隊那邊提過issue,但是暫時沒有辦法處理,我後續會提到一個另闢蹊徑的方案,先回到這裏,點了這個全屏按鈕之後會進入微信的全屏播放模式,而且放完之後會出現一堆廣告列表,這都是我們不想看到了,其次如果我們的產品需求不單單是全屏播放,還想在視頻上面放一些交互按鈕之類的,這種方式就做不到,因爲video是在最上一級的,但是兩種方式例外,一個是微信把你們的域名加入白名單,這種可以在Android手機的video上隨意放置dom元素,IOS本身沒有這個限制,另一種更爲通用的方式是用微信x5內核的同層播放模式,這種模式有兩種好處:
- 去除了右上角討厭的”全屏”按鈕
- 真正實現了x5內核下的沉浸式播放,我們看到目前的實現在微信上還是帶有瀏覽器的titleBar的 在x5內核的環境下實現同層播放很簡單,只需要在video上添加這麼兩行屬性:
- x5-video-player-type="h5"
- x5-video-player-fullscreen="true"
再看一下這個時候的效果:
同層播放模式下的效果
確實是真正意義上的沉浸式播放,如果你的app裏面webview用的也是x5內核那麼這個頁面也能在app上達到同樣的效果,但是這種同層播放依然有無法解決的問題,首先這個全屏模式會重新計算寬高,觸發視口大小變化,也就是說用戶視覺上會有一個視口變化的過程,其次,同層播放模式雖然沒有了”全屏”按鈕,但是左上角的按鈕用於退出沉浸式全屏,右上角的按鈕點開是分享,分享的內容不可定製,固定位當前頁面的title+url的組合,如果你對頁面的定製化要求比較高的話,我這裏有一個備選的方案,那就是放棄同層播放模式,當然這個前提是你不需要在video頁面上做一些交互操作,或者說你的域名處於微信白名單下,當我們在非沉浸式下又想要打到等比例縮放視頻的效果,同時我們還要去除x5自帶的”全屏”按鈕,最好的方式就是動態去計算視頻的寬高,把視頻撐大,把”全屏”按鈕撐出瀏覽器頁面,這樣基本就能達到我們的目的了,這裏以16:9的標準爲例:
- this.$nextTick(() => {
- // 動態處理video標籤寬高適配
- const video = this.$refs.video
- const ratio = Math.fround(document.documentElement.clientHeight / document.documentElement.clientWidth)
- if (ratio >= 1.78) {
- // 豎屏
- video.height = document.documentElement.clientHeight + 100
- video.width = Math.floor(video.clientHeight * 0.572)
- const winW = document.documentElement.clientWidth
- video.style.left = (winW - video.width) / 2 + 'px'
- } else {
- // 寬屏
- video.width = document.documentElement.clientWidth + 100
- video.height = Math.floor(video.width * 1.78)
- const winH = document.documentElement.clientHeight
- video.style.top = (winH - video.height) / 2 + 'px'
- }
- })
講解下思路,16:9的視頻也就是高寬比差不多是1.78,那麼大於這個比例的就是類似於iphoneX的長屏幕類型的手機,對於這種手機我們要做等比縮放適配的話就以手機的長爲標準,先讓視頻的長度等於手機的長度,這裏我加上的100px可以理解爲上下在加上50px,目的就是爲了把視頻長度拉大,讓”全屏”按鈕消失在視線內,實際這個值可以自己嘗試修改,讓後寬就是此時高的1/78倍,然後使用絕對佈局去設置視頻的左邊距,就可以達到等比縮放的效果,同理可以理解處理寬屏手機的代碼部分,當然,應該還有更完美的方案,可以在評論區留言探討~
作者:李牧羊
https://www.limuyang.cc/2018/07/22/video標籤沉浸式播放解決方案/