如今,在網頁上播放視頻已經愈來愈流行,可是網上的資料魚龍混雜,很難找到本身想要的,今天小編就本身的親身開發體驗,手把手從零開始---封裝一個vue視頻播放器組件。css
做爲一個老道的前端搬磚師,怎麼可能會一心閉門造車呢?仍是先去網上找找輪子吧html
通過在網上不斷的查閱以後,我最終選擇了video.js這個輪子,做爲個人播放器。好,如今輪子找好了,乍一看,天,好像有點醜。不着急,我再來把它美化美化(二次封裝)。前端
//安裝video.js插件 npm install video.js -S //若是須要播放rtmp直播流,需安裝一下插件 npm install videojs-flash -S 複製代碼
<template>
<div> <div data-vjs-player> <video ref="videoNode" class="video-js vjs-default-skin">抱歉,您的瀏覽器不支持</video> </div> </template> 複製代碼
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經常使用的配置項:vue
除非另有說明,不然默認狀況下每一個選項undefinedhtml5
類型: stringweb
將播放器置於流體模式,並在計算播放器的動態大小時使用該值。該值應表示比率 - 由冒號(例如"16:9"或"4:3")分隔的兩個數字。面試
類型: booleannpm
阻止播放器爲具備data-setup屬性的媒體元素運行autoSetup 。json
注意:必須在與videojs.options.autoSetup = falsevideojs源加載生效的同一時刻全局設置。api
類型: boolean
設置爲true,Video.js播放器將具備流暢的大小。換句話說,它將擴展以適應其容器。
此外,若是元素具備"vjs-fluid",則此選項自動設置爲true。
類型: number
Video.js表示用戶經過"vjs-user-active"和"vjs-user-inactive"類以及"useractive"事件與玩家進行交互。
在inactivityTimeout決定了不活動的許多毫秒聲明用戶閒置以前是必需的。值爲0表示沒有inactivityTimeout,用戶永遠不會被視爲非活動狀態。
鍵入:string,默認值:瀏覽器默認值或’en’
與播放器中的一種可用語言匹配的語言代碼。這爲播放器設置了初始語言,但始終能夠更改。
在Video.js中瞭解有關語言的更多信息。
類型: Object
自定義播放器中可用的語言。此對象的鍵將是語言代碼,值將是具備英語鍵和翻譯值的對象。
在Video.js中瞭解有關語言的更多信息
注意:一般,不須要此選項,最好將自定義語言傳遞給videojs.addLanguage()全部玩家!
類型: boolean
明確設置關聯技術選項的默認值。
類型: string
容許覆蓋Video.js沒法播放媒體源時顯示的默認消息。
類型: Array
嚴格大於0的數字數組,其中1表示常速(100%),0.5表示半速(50%),2表示雙速(200%)等。若是指定,Video.js顯示控件(類vjs-playback-rate)容許用戶從選擇數組中選擇播放速度。選項以從下到上的指定順序顯示。
例如:
videojs('my-player', {
playbackRates: [0.5, 1, 1.5, 2] }); 複製代碼
類型: 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> 複製代碼
類型: boolean
使技術人員有可能覆蓋玩家的海報並融入玩家的海報生命週期。當使用多個技術時,這可能頗有用,每一個技術都必須在播放新源時設置本身的海報。
輸入:Array,默認值:[‘html5’]
定義Video.js技術首選的順序。默認狀況下,這意味着Html5首選技術。其餘註冊的技術將在此技術以後按其註冊順序添加。
類型: boolean
能夠設置爲false禁用本機視頻軌道支持。最經常使用於videojs-contrib-hls。
類型: boolean
只有技術支持Html5,此選項能夠設置true爲強制觸摸設備的本機控件。
按照上面簡單的使用方式使用以後,咱們會發現視頻播放待播放頁面是這樣的:
播放按鈕默認在左上角,是做者認爲會遮擋內容考慮的,不過這個是能夠根據參數修改的,咱們只須要給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這個輪子來實現該功能。
npm i videojs-markers -S
複製代碼
import "videojs-markers";
//引入樣式 import "videojs-markers/dist/videojs.markers.css"; 複製代碼
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的方式從父組件中傳入。
注:此處只列舉了部分,能夠示實際狀況添加或者刪除
根據這些屬性,咱們來改造一下咱們的組件
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
近期好文推薦:
最後,若是你們想和我一塊兒討論探索前端,能夠關注一下個人公衆號,不按期更新干貨,關注以後後臺回覆知識體系,更可領取小編精心準備的前端知識體系,將來學習再也不迷茫。更可加入技術羣交流討論。
本文使用 mdnice 排版