筆者近來在用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