手把手從零開始---封裝一個vue視訊播放器元件
現在,在網頁上播放視訊已經越來越流行,但是網上的資料魚龍混雜,很難找到自己想要的,今天小編就自己的親身開發體驗,手把手從零開始---封裝一個vue視訊播放器元件。
作為一個老道的前端搬磚師,怎麼可能會一心閉門造車呢?還是先去網上找找輪子吧
經過在網上不斷的查閱之後,我最終選擇了video.js這個輪子,作為我的播放器。好,現在輪子找好了,乍一看,天,好像有點醜。不著急,我再來把它美化美化(二次封裝)。
引入video.js
安裝
//安裝video.js外掛
npm install video.js -S //如果需要播放rtmp直播流,需安裝一下外掛
npm install videojs-flash -S
在元件中簡單使用外掛
template
<template>
<div>
<div data-vjs-player>
<video ref="videoNode" class="video-js vjs-default-skin">抱歉,您的瀏覽器不支援</video>
</div>
</template>
script
import videojs from "video.js";
//播放器中文,不能使用.js檔案
import videozhCN from "video.js/dist/lang/zh-CN.json";
//樣式檔案注意要加上
import "video.js/dist/video-js.css";
//如果要播放RTMP要使用flash 需要先npm i videojs-flash
import "videojs-flash";
export default {
data() {
return {
player: null,
};
},
//初始化播放器
mounted(){
let options = {
autoplay: true, //自動播放
language: "zh-CN",
controls: this.controls, //控制條
preload: "auto", //自動載入
errorDisplay: true, //錯誤展示
// fluid: true, //跟隨外層容器變化大小,跟隨的是外層寬度
width: "500px",
height: "500px",
// controlBar: false, // 設為false不渲染控制條DOM元素,只設定controls為false雖然不展示,但是存在
// textTrackDisplay: false, // 不渲染字幕相關DOM
userActions: {
hotkeys: true //是否支援熱鍵
},
notSupportedMessage: "此視訊暫無法播放,請稍後再試",
techOrder: ["h5","flash"],//定義Video.js技術首選的順序
sources: [
{
src: '視訊或者直播地址',
type: 'video/mp4',
//type: 'rtmp/flv',
}
]
};
this.player = videojs(
this.$refs.videoNode,
options,
function onPlayerReady() {
videojs.log(`Your player is ready!`);
}
);
videojs.addLanguage("zh-CN", videozhCN);
},
beforeDestroy() {
if (this.player) {
this.player.dispose();
}
}
}
這樣一個簡單的視訊播放功能就實現了。這裡小編也給大家整理了一些video.js常用的配置項:
常用選項
- autoplay:true/false 播放器準備好之後,是否自動播放 【預設false】
- controls:true/false 是否擁有控制條 【預設true】,如果設為false ,那麼只能通過api進行控制了。也就是說介面上不會出現任何控制按鈕
- height: 視訊容器的高度,字串或數字 單位畫素 比如: height:300 or height:‘300px‘
- width: 視訊容器的寬度, 字串或數字 單位畫素
- loop : true/false 視訊播放結束後,是否迴圈播放
- muted : true/false 是否靜音
- poster: 播放前顯示的視訊畫面,播放開始之後自動移除。通常傳入一個URL
- preload:預載入 ‘auto‘ 自動、、’metadata‘ 元資料資訊,比如視訊長度,尺寸等、‘none‘ 不預載入任何資料,直到使用者開始播放才開始下載
Video.js特定的選項
除非另有說明,否則預設情況下每個選項undefined
aspectRatio
型別: string
將播放器置於流體模式,並在計算播放器的動態大小時使用該值。該值應表示比率 - 由冒號(例如"16:9"或"4:3")分隔的兩個數字。
autoSetup
型別: boolean
阻止播放器為具有data-setup屬性的媒體元素執行autoSetup 。
注意:必須在與videojs.options.autoSetup = falsevideojs源載入生效的同一時刻全域性設定。
fluid
型別: boolean
設定為true,Video.js播放器將具有流暢的大小。換句話說,它將擴充套件以適應其容器。
此外,如果元素具有"vjs-fluid",則此選項自動設定為true。
inactivityTimeout
型別: number
Video.js表示使用者通過"vjs-user-active"和"vjs-user-inactive"類以及"useractive"事件與玩家進行互動。
在inactivityTimeout決定了不活動的許多毫秒宣告使用者閒置之前是必需的。值為0表示沒有inactivityTimeout,使用者永遠不會被視為非活動狀態。
language
鍵入:string,預設值:瀏覽器預設值或’en’
與播放器中的一種可用語言匹配的語言程式碼。這為播放器設定了初始語言,但始終可以更改。
在Video.js中瞭解有關語言的更多資訊。
languages
型別: Object
自定義播放器中可用的語言。此物件的鍵將是語言程式碼,值將是具有英語鍵和翻譯值的物件。
在Video.js中瞭解有關語言的更多資訊
注意:通常,不需要此選項,最好將自定義語言傳遞給videojs.addLanguage()所有玩家!
nativeControlsForTouch
型別: boolean
明確設定關聯技術選項的預設值。
notSupportedMessage
型別: string
允許覆蓋Video.js無法播放媒體源時顯示的預設訊息。
playbackRates
型別: Array
嚴格大於0的數字陣列,其中1表示常速(100%),0.5表示半速(50%),2表示雙速(200%)等。如果指定,Video.js顯示控制元件(類vjs-playback-rate)允許使用者從選擇陣列中選擇播放速度。選項以從下到上的指定順序顯示。
例如:
videojs('my-player', {
playbackRates: [0.5, 1, 1.5, 2]
});
sources
型別: Array
一組物件,它們反映了本機元素具有一系列子元素的能力。這應該是帶有src和type屬性的物件陣列。例如:
videojs('my-player', {
sources: [{
src: '//path/to/video.mp4',
type: 'video/mp4'
}, {
src: '//path/to/video.webm',
type: 'video/webm'
}]
});
使用元素將具有相同的效果:
<video ...>
<source src="//path/to/video.mp4" type="video/mp4">
<source src="//path/to/video.webm" type="video/webm">
</video>
techCanOverridePoster
型別: boolean
使技術人員有可能覆蓋玩家的海報並融入玩家的海報生命週期。當使用多個技術時,這可能很有用,每個技術都必須在播放新源時設定自己的海報。
techOrder
輸入:Array,預設值:[‘html5’]
定義Video.js技術首選的順序。預設情況下,這意味著Html5首選技術。其他註冊的技術將在此技術之後按其註冊順序新增。
nativeVideoTracks
型別: boolean
可以設定為false禁用本機視訊軌道支援。最常用於videojs-contrib-hls。
nativeControlsForTouch
型別: boolean
只有技術支援Html5,此選項可以設定true為強制觸控裝置的本機控制元件。
美化video.js輪子
播放按鈕居中
按照上面簡單的使用方式使用之後,我們會發現視訊播放待播放頁面是這樣的:
播放按鈕預設在左上角,是作者認為會遮擋內容考慮的,不過這個是可以根據引數修改的,我們只需要給video標籤加一個class(vjs-big-play-centered)就可以了。
<video ref="videoNode" class="video-js vjs-default-skin vjs-big-play-centered"></video>
加完之後效果如下:
載入中狀態美化
video.js在播放視訊的時候,有一個預設的載入中,這裡我根據自己的想法提供了一種自定義載入中頁面的思路,如有錯,請大佬指正。
主要思路:
在播放器的上面懸浮覆蓋一層div,用於顯示自定義載入中的內容,再通過一個變數值控制這個div是否載入,通過監聽視訊的一個載入狀態更新變數的值,以達到自定義載入中頁面的目的。
主要程式碼:
template
注:不是完整程式碼,只是關鍵程式碼
<div :style="{width:'100%',position:'relative',height:height}">
<div data-vjs-player style="width:100%">
<video ref="videoNode" class="video-js vjs-default-skin vjs-big-play-centered">抱歉,您的瀏覽器不支援</video>
</div>
<div
v-if="loading"
:style="{width:'100%',height:height,position:'absolute',left:'0px',top:'0px'}"
>
<img
:style="{width:'100%',height:height}"
src="https://img.zcool.cn/community/0113b1576a43e90000018c1b87042d.gif"
/>
</div>
</div>
script
注:不是完整程式碼,只是關鍵程式碼
data() {
return {
loading: false
};
},
let options = {
autoplay: false, //自動播放
.....省略程式碼
};
this.player = videojs(
this.$refs.videoNode,
options,
function onPlayerReady() {
videojs.log(`Your player${self.index} is ready!`);
_this.loading = true;
_this.player.play();
_this.player.one("playing", function() {
// 監聽播放
// console.log("播放器開始播放");
_this.loading = false;
});
}
);
效果如下:
當然,內容你也可以自定義。
視訊打點
平時生活中,我們在看視訊的時候,經常會看到,有些視訊的進度條上面有一些小點,然後滑鼠放上去會出現一些文字提示,那麼我們的web播放器上面能不能也新增這個功能呢?當然是可以的!
首先還是去找了一波輪子,最後找到了videojs-markers這個輪子來實現該功能。
安裝videojs-markers
npm i videojs-markers -S
引入videojs-markers
import "videojs-markers";
//引入樣式
import "videojs-markers/dist/videojs.markers.css";
使用videojs-markers
this.player.markers({
markerStyle: {
// 標記點樣式
width: "0.7em",
height: "0.7em",
bottom: "-0.20em",
"border-radius": "50%",
"background-color": "orange",
position: "absolute"
},
//滑鼠移入標記點的提示
markerTip: {
display: true,//是否顯示
/*
用於動態構建標記提示文字的回撥函式。
只需返回一個字串,引數標記是傳遞給外掛的標記物件
*/
text: function(marker) {
return marker.text;
}
},
markers: [
{
time: 20,
text:'點位一'
},
{
time: 40,
text:'點位二'
},
{
time: 130,
text:'點位三'
},
{
time: 200,
text:'點位四'
}
],
});
效果如下:
封裝元件
播放器基本功能實現了,那麼最後一步就是封裝元件了。封裝的思路很簡單,就是將一些變化的屬性通過props的方式從父元件中傳入。
常用需要封裝的屬性
注:此處只列舉了部分,可以示實際情況新增或者刪除
- src : 視訊或者直播的地址
- height :播放器的高度
- controls :控制條是否需要顯示
- markers :視訊打點的資料來源
- type :播放視訊的型別
根據這些屬性,我們來改造一下我們的元件
template
<template>
<div :style="{width:'100%',position:'relative',height:height}">
<div data-vjs-player style="width:100%">
<video ref="videoNode" class="video-js vjs-default-skin vjs-big-play-centered">抱歉,您的瀏覽器不支援</video>
</div>
<div
v-if="loading"
:style="{width:'100%',height:height,position:'absolute',left:'0px',top:'0px'}"
>
<img
:style="{width:'100%',height:height}"
src="https://img.zcool.cn/community/0113b1576a43e90000018c1b87042d.gif"
/>
</div>
</div>
</template>
script
data() {
return {
player: null,
loading: false
};
},
let options = {
// autoplay: true, //自動播放
language: "zh-CN",
controls: this.controls, //控制條
preload: "auto", //自動載入
errorDisplay: true, //錯誤展示
// fluid: true, //跟隨外層容器變化大小,跟隨的是外層寬度
width: "100%",
height: this.height,
// controlBar: false, // 設為false不渲染控制條DOM元素,只設定controls為false雖然不展示,但還是存在
// textTrackDisplay: false, // 不渲染字幕相關DOM
userActions: {
hotkeys: true //是否支援熱鍵
},
notSupportedMessage: "此視訊暫無法播放,請稍後再試",
techOrder: ["flash"],
sources: [
{
src: this.src,
type: this.type
}
]
};
let _this = this;
this.player = videojs(
this.$refs.videoNode,
options,
function onPlayerReady() {
videojs.log(`Your player${self.index} is ready!`);
_this.loading = true;
_this.player.play();
_this.player.one("playing", function() {
// 監聽播放
// console.log("播放器開始播放");
_this.loading = false;
});
}
);
videojs.addLanguage("zh-CN", videozhCN);
if (this.markers) {
this.player.markers({
markerStyle: {
// 標記樣式
width: "0.7em",
height: "0.7em",
bottom: "-0.20em",
"border-radius": "50%",
"background-color": "orange",
position: "absolute"
},
markerTip: {
display: true,
/*
用於動態構建標記提示文字的回撥函式。
只需返回一個字串,引數標記是傳遞給外掛的標記物件
*/
text: function(marker) {
return marker.text;
}
},
markers: this.markers,
});
}
動態切換視訊封裝
在視訊播放的時候,我們經常會有視訊切換之類的需求,那麼這個怎麼封裝呢?很簡單,只需要在元件中監聽src的變化,如果src發生了變化,那麼就重新載入視訊,播放視訊,程式碼如下:
watch: {
src() {
if (this.player) {
let _this = this;
this.loading = true;//重新顯示載入狀態
let myPlayer = this.player;
myPlayer.off("timeupdate");//清空時間
myPlayer.reset();//重置播放器
myPlayer.pause();//暫停播放
myPlayer.src([//重新設定播放源
{
src: this.src,
type: "rtmp/flv"
}
]);
myPlayer.load(this.src);//重新載入視訊
myPlayer.play();//播放視訊
myPlayer.one("playing", function() {
// 載入完成,開始播放
// console.log("播放器開始播放");
_this.loading = false;//隱藏載入狀態
});
}
}
},
這樣一個簡單的視訊播放器就封裝好了。
使用示例
元件封裝完成,免不了使用一下,程式碼如下:
<template>
<basic-container>
<el-row class="video-test">
<el-col :span="16" class="video-test-left">
<videoPlayer :controls="true" height="600px" :src="url" type="video/mp4" :markers="markers"/>
</el-col>
</el-row>
</basic-container>
</template>
<script>
import videoPlayer from "@/components/videoPlayer/videoPlayer";
export default {
components: { videoPlayer },
data() {
return {
url: "http://127.0.0.1/test.mp4",
markers: [
{
time: 20,
text:'點位一'
},
{
time: 40,
text:'點位二點位二點位二點位二點位二點位二點位二點位二'
},
{
time: 130,
text:'點位三點位三點位三點位三點位三點位三'
},
{
time: 200,
text:'點位四點位四點位四點位四點位四點位四'
}
]
};
}
};
</script>
<style lang="scss">
</style>
參考:
videojs中文檔案詳解 https://blog.csdn.net/a0405221/article/details/80923090