手把手從零開始---封裝一個vue視頻播放器組件

如今,在網頁上播放視頻已經愈來愈流行,可是網上的資料魚龍混雜,很難找到本身想要的,今天小編就本身的親身開發體驗,手把手從零開始---封裝一個vue視頻播放器組件。css

做爲一個老道的前端搬磚師,怎麼可能會一心閉門造車呢?仍是先去網上找找輪子吧html

通過在網上不斷的查閱以後,我最終選擇了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經常使用的配置項:vue

經常使用選項
  • 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特定的選項

除非另有說明,不然默認狀況下每一個選項undefinedhtml5

aspectRatio

類型: stringweb

將播放器置於流體模式,並在計算播放器的動態大小時使用該值。該值應表示比率 - 由冒號(例如"16:9"或"4:3")分隔的兩個數字。面試

autoSetup

類型: booleannpm

阻止播放器爲具備data-setup屬性的媒體元素運行autoSetup 。json

注意:必須在與videojs.options.autoSetup = falsevideojs源加載生效的同一時刻全局設置。api

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

近期好文推薦:

一、史上最強vue總結~萬字長文---面試開發全靠它了

二、有了它,你的項目將快過火箭

三、Event Loop我知道,宏任務微任務是什麼鬼?

四、鋒利碼農武器之vscode

五、面試寶典帶你走上人生巔峯

最後,若是你們想和我一塊兒討論探索前端,能夠關注一下個人公衆號,不按期更新干貨,關注以後後臺回覆知識體系,更可領取小編精心準備的前端知識體系,將來學習再也不迷茫。更可加入技術羣交流討論。

本文使用 mdnice 排版

相關文章
相關標籤/搜索