博客 / 詳情

返回

h5 video踩坑記錄

筆者近來在用h5 的video來開發視頻,下面來聊一聊是怎麼一步一步填坑的。
一些在開發中的注意點,都在代碼裏的註釋進行描述

基本需求

  • 禁止全屏
  • 是否自動播放
  • 播放器尺寸的設置
  • 播放完畢時回到初始狀態

1. 禁止全屏

webkit-playsInline={true} // ios
x5-playsInline ={true}// android
playsInline ={true}//ios10

注意:筆者在這裏用的是video-react,所以是playsInline,如果使用原生video的話,是playsinline

2. 是否自動播放

  • 設置自動播放需要設置autoPlay屬性
  • 筆者所遇到的需求是,由後端接口控制是否默認播放,所以在這裏分為兩個步驟
// 步驟1:在video標籤裏設置autoPlay=false
<VideoReact
    src={video_url}
    webkit-playsInline={true}
    x5-playsInline ={true}
    playsInline ={true}

    autoPlay={false} 
</VideoReact>

// 步驟2:根據接口的返回值來設置自動播放
handleVideoPlay = (is_first) => {
    let { item: {video_play}, ref_name } = this.props;
    let ref_name_state = this.state.ref_name;
    let video = this[ref_name_state].video;
    if(video_play){// 自動播放, video_play由後端返回
        if(is_first){
            // 首次播放時加延時,避免了在視頻未加載成功時就播放
            this.video_timeout = setTimeout(() => {
                video.play();
            }, 300)
        }
    }
}

3. 播放器尺寸的設置

在這裏,採用固定視頻的寬度,根據視頻的封面尺寸來計算視頻的高度的算法。

  • 在使用video-react時,發現設置height時,不能使用rem尺寸,只能用px和%,但是後兩種單位不能兼容不同的分辨率。所以在這裏採用控制視頻外層div的尺寸的方法,而將視頻的尺寸都設置為100%
// 有封面尺寸時,根據封面的寬高比計算高度;沒有封面尺寸時,根據16:9計算高度
let video_height_cal = cover_width ? ((710 * (cover_height/cover_width)/100)): 3.9938;
return (
 <div style={{height: video_height_cal+'rem', width: '7.1rem'}}> // 視頻外層div的尺寸設置
    <VideoReact
        src={video_url}
        webkit-playsInline={true} 
        x5-playsInline ={true}
        playsInline ={true}

        autoPlay={false} 
        width={'100%'}
        height={'100%'}
    </VideoReact>
</div>   
)
  • 經過以上設置之後,視頻外層div、播放器、video、封面的尺寸都保持了一致,但是在實際上,卻還是在部分機型上有黑邊出現(黑邊:播放器的背景色,有黑邊説明視頻和封面沒有完全遮蓋播放器)

    • 解決辦法:增大封面和視頻的尺寸,以使其能完全遮蓋播放器
.video-react-poster{
    height: 100.1%; // 增大封面的高度,
    top: -0.1px; // 調整位置
    
    // 額外問題
    // 禁止封面的圖片重複展示
    background-repeat: no-repeat; 
    // 儘可能的縮放背景並保持圖像的寬高比例
    background-size: contain; 
    // 設置完上一個屬性後,發現圖片並不是上下居中的,所以設置了背景的起始位置
    background-position: center; 
}

.video-react-has-started{
        .video-react-video{
            height: 100.3%; //增大視頻的高度
            width: auto;//視頻的寬度自適應
            top: -0.4px; // 調整位置
            left: -0.2px;

            // 額外問題
            // 設置max-width是為了避免在將視頻全屏播放時,寬度還是auto導致超出屏幕寬度的現象
            max-width: 110%;
        }
    }

4. 播放完畢時回到初始狀態

  • 採用的方法是:播放結束時,重新load當前視頻
componentDidMount() {
    this.videoLoadSuccess();
}

videoLoadSuccess = () => {
    let video = document.querySelector('video');
    let { ref_name }  =this.state;

    // 在視頻達到可以播放的狀態時,監聽其狀態變化
    video.addEventListener('canplaythrough', (event) => {
           // 由於canplaythrough會觸發多次,所以在這裏添加了對canplaythrough觸發的限制,只有當緩存數組裏沒有該值時,才去監聽
           if(!play_through_cache[ref_name]){
                play_through_cache[ref_name] = 1;
                this[ref_name].subscribeToStateChange(this.handleStateChange);
            }
    })
}

// 根據視頻的狀態變化,判斷其是否播放完成
handleStateChange = (state, preState) = > {
    // 視頻播放結束回到初始狀態(進度條)
    if(state.ended && !prevState.ended){
        this[this.state.ref_name].video.load();
    }
}

希望大家能持續關注哦,留一些個人信息方便大家找到我哦。
github

user avatar laughingzhu 頭像 jidongdehai_co4lxh 頭像 susouth 頭像 jianqiangdepaobuxie 頭像 weirdo_5f6c401c6cc86 頭像 ailim 頭像 gaoming13 頭像 mulander 頭像 liyl1993 頭像 iymxpc3k 頭像 fehaha 頭像 warn 頭像
19 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.