X5同層播放器應用實踐

移動端瀏覽器中的video元素是比較特別的,早期不管是在iOS仍是Android的瀏覽器中,它都位於頁面的最頂層,沒法被遮擋。後來,這個問題在iOS下獲得瞭解決。可是對Android的大部分瀏覽器來講,問題仍然存在。X5是騰訊基於Webkit開發的瀏覽器內核,應用於Android端的微信、QQ、QQ瀏覽器等應用。它提供了一種名叫「同層播放器」的特殊video元素以解決遮擋問題。css

簡單使用

只要給普通的video元素加上X5的自定義屬性 x5-video-player-type ,就能夠調用同層播放器。示例代碼以下:html

body {
    margin: 0;
    background: #000;
}
.video {
    width: 100%;
}
複製代碼
<div class="player">
    <video id="video" class="video" controls="controls" playsinline x5-video-player-type="h5">
        <source src="video.mp4" />
    </video>
</div>
複製代碼

點擊播放後,頁面會瞬間拉伸(體驗有點差),而後就進入了全屏狀態,視頻默認在中間位置:web

同層播放器默認UI

調整位置

在全屏狀態下,調整視頻位置的通用作法是:把video元素的尺寸設成滿屏,再經過 object-position 樣式屬性控制視頻內容的位置。相關代碼以下:瀏覽器

.fullscreen .video {
    object-position: center top;
}
複製代碼
var player = document.getElementById('video');
var isFullScreen;

// 進入全屏,設置狀態
player.addEventListener('x5videoenterfullscreen', function() {
    isFullScreen = true;
    // 在body上添加樣式類以控制全屏狀態下的頁面佈局
    document.body.classList.add('fullscreen');
}, false);

// 退出全屏時,清空狀態
player.addEventListener('x5videoexitfullscreen', function() {
    isFullScreen = false;
    document.body.classList.remove('fullscreen');
    player.style.width = player.style.height = '';
}, false);

// 同層播放器進入全屏狀態會致使窗口resize,但退出全屏不會
window.addEventListener('resize', function() {
    if (isFullScreen) {
        // 設爲屏幕尺寸
        player.style.width = window.screen.width + 'px';
        player.style.height = window.screen.height + 'px';
    }
}, false);
複製代碼

效果以下方左圖所示,可見,此時視頻距離頂部尚有一些距離。這個問題與 x5-video-player-fullscreen 屬性有關。若是不聲明這個屬性,原標題欄的佔位不會分配給頁面,而是平均分紅上下兩塊,分別位於窗口頂部和底部。所以,視頻沒法頂到最上方。微信

x5-video-player-fullscreen 的做用

補充 x5-video-player-fullscreen 屬性後,問題就解決了(上方右圖):ide

<video id="video" class="video" controls="controls" playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true">
    <source src="video.mp4" />
</video>
複製代碼

你們還能夠發現,頂部有一層黑色漸變(上圖不太明顯,能夠看下文的圖)以及兩個按鈕。據官方文檔所述,這些都是沒法移除的。佈局

全屏狀態下的佈局

實際業務中,頁面多半不會只有一個視頻這麼簡單,下面就開始添加其餘頁面元素(請行引入rem佈局所需的腳本)。首先是在視頻以前加上標題欄:ui

.header {
    width: 100%;
    height: 1.14rem;
    line-height: 1.14rem;
    background: #fff;
    font-size: 0.36rem;
    text-align: center;
    color: #000;
}
複製代碼
<header id="header" class="header">標題欄</header>
<div class="player">
    <video id="video" class="video" controls="controls" playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true">
        <source src="video.mp4" />
    </video>
</div>
複製代碼

然而,點擊播放進入全屏狀態後,標題欄就消失了,其實它是被視頻擋住了。既然同層播放器是能夠被遮擋的,那能夠試試絕對定位:spa

.fullscreen .header {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 9999;
}
複製代碼

從下方左圖可見,標題欄確實能夠擋住視頻了。code

標題欄

此時視頻內容被遮擋,因此要將其下移(上方右圖):

.fullscreen .video {
    object-position: center 1.14rem;
}
複製代碼

接下來在視頻以後添加其餘頁面元素,常規作法是限制視頻區域高度,再進行後面的佈局。但因爲video元素自己在全屏狀態下的寬高必須設成滿屏,因此只能經過它的父元素(div.player)限制它的佔位:

.player {
    height: 4.22rem;
}
.fullscreen .player {
    /* 全屏狀態下重設高度,勿忘 */
    height: 5.36rem; /* 4.22 + 1.14 */
}
.video {
    width: 100%;
    height: 100%;
}
.main {
    box-sizing: border-box;
    padding: 0.3rem;
    height: 5rem;
    background: #fff;
}
複製代碼
<header id="header" class="header">...</header>
<div class="player">...</div>
<div id="main" class="main">這裏是其餘內容</div>
複製代碼

而div.main自己是不須要作任何特殊處理的。然而,此時又出現了一個新問題:進入全屏狀態後,視頻控制欄不見了。緣由是,video元素的高度爲屏幕高度,控制欄位於屏幕最底端,而div.player又限制了高度,致使video元素超出的區域被隱藏,天然就看不到控制欄了。幸虧,咱們還能夠經過僞元素選擇器修改控制欄的樣式:

.fullscreen .player {
    position: relative;
    height: 5.36rem;
}
.fullscreen .video::-webkit-media-controls {
    position: absolute;
    bottom: 0;
}
複製代碼

經過使控制欄相對於div.player定位,就可讓它回到視頻畫面的底端了。最終效果以下圖所示:

最終效果

綜上所述,在全屏狀態下,video元素以前的元素須要作佈局調整,而在其後的元素則不須要

頁面滾動

若是頁面有滾動條,進入全屏狀態後,是否還能夠滾動呢?

筆者撰寫本文初版(2017年中)的時候,全屏狀態下的頁面滾動會變成抖動,效果很是糟糕,而目前則是滾不了了。

因此,若是頁面內容確實較多,只能使用元素內滾動了

控制欄的坑

不得不說,原生控制欄的bug很是嚴重。

Bug 1:播放某些格式的視頻時,進度條會出現錯亂,即便退出全屏模式也仍是錯亂。

進度條錯亂

Bug 2:控制欄的全屏按鈕在某些狀況(具體規律還沒有查明)下無效。

Bug 3:整個控制欄在某些狀況(具體規律還沒有查明)下沒法調出。

以上三個bug非必現。但爲了躲開這些坑,建議屏蔽原生控制欄,自行開發一個控制欄。

視頻全屏的實現

上一節提到,原生控制欄的全屏按鈕在某些狀況下無效,這樣一來就必須想其餘方法去實現視頻的全屏了,這裏面最關鍵就是video元素的 x5-video-orientation 屬性。它決定了同層播放器進入全屏狀態後,當前窗口是橫屏仍是豎屏(前文的全部描述中,都是豎屏的狀況)。而且,它是能夠動態設置的。

若是把 x5-video-orientation 設成橫屏,再把頁面上的其餘元素隱藏掉,就跟全屏無異了。具體實現以下:

var isLandscape;

// 點擊其餘內容區域,進入全屏
var main = document.getElementById('main');
main.addEventListener('click', function() {
    // 同層播放器進入全屏狀態以後,才能讓視頻全屏
    if (!isFullScreen) { return; }
    // 修改 x5-video-orientation
    player.setAttribute('x5-video-orientation', 'landscape');

    isLandscape = true;
}, false);

// 檢測窗口方向改變,修改佈局
window.addEventListener('orientationchange', function() {
    if (isLandscape) {
        document.body.classList.add('landscape');
        var width = window.screen.width;
        var height = window.screen.height;
        player.style.width = width + 'px';
        player.style.height = height + 'px';
        
    }
}, false);
複製代碼
.landscape .header { display: none; }
.landscape .video { object-position: center center; }
.landscape .main { display: none; }
複製代碼

要強調的是,從修改 x5-video-orientation 到窗口方向改變,須要必定的時間才能完成。所以,不要在修改以後立刻調整佈局,而是要監聽 window 的 orientationchange 事件,在事件回調中調整佈局。此外,還要在退出全屏時,清空相關狀態:

player.addEventListener('x5videoexitfullscreen', function() {
    isFullScreen = false;
    isLandscape = false;
    document.body.classList.remove('fullscreen', 'landscape');
    player.style.width = player.style.height = '';
}, false);
複製代碼

最終效果以下(頂部的陰影和兩個按鈕仍然沒法幹掉):

視頻全屏效果

後記

本文初版寫於2017年6月,當時剛接觸同層播放器,因此文章內容只能算是一份試用報告。通過一年多的項目實踐以後,有些舊問題找到了更好的解決方案,還發現並解決了一些新問題,而同層播放器自己也有一些變化,因而在2018年11月進行修訂,發佈第二版。

本文同時發佈於做者我的博客: mrluo.life/article/det…

相關文章
相關標籤/搜索