从0到1搭建一款Vue可配置视频播放器组件

 前言

话不多说,搭建这篇文章主要讲述如何从0到1搭建一款适用于Vue.js的款V可配自定义配置视频播放器。我们平时在PC端网站上观看视频时,置视组件会看到有很多丰富样式的频播视频播放器,而我们自己写的放器video标签样式却是那么丑。其实像那些网站都是搭建基于原生video标签进行开发的,只不过还得适当加工一下,款V可配才会有我们所看到的置视组件漂亮的视频播放器。

开发

在具体开发之前,频播我们需要明确我们需要做什么?放器

封装一个可配置的视频播放器; 适用于Vue.js; 应用于PC端网站; 视频播放器常用的功能必须要有; 发布到Npm;

好,明确了以上几点之后,搭建我们就开始敲代码了。款V可配

一、置视组件搭建一个基础的频播UI组件

这里的UI组件你可以理解成我们搭建一个静态页面,就是放器把视频播放器简单地搭建起来,有一个基础的模型。

<template>   <div     class="video-box"   >     <video       class="video-player"     ></video>     <div class="bottom-tool">       <div class="pv-bar">         <div class="pv-played"></div>         <div class="pv-dot"></div>       </div>       <div class="pv-controls">         <div class="pc-con-l">           <div class="play-btn">             <i class="iconfont icon-bofang"></i>             <i class="iconfont icon-zanting hide"></i>           </div>           <div class="pv-time">             <span class="pv-currentTime">00:00:00</span>             <span>/</span>             <span class="pv-duration">00:00:00</span>           </div>         </div>         <div class="pc-con-r">           <div class="pv-listen ml">             <div class="pv-yl">               <p class="pv-ol"></p>               <p class="pv-bg"></p>             </div>             <div class="pv-iconyl">               <i class="iconfont icon-yinliang"></i>               <i class="iconfont icon-jingyin hide"></i>             </div>           </div>           <div class="pv-speed ml">             <p class="pv-spnum">1x</p>             <ul class="selectList">               <li>0.5x</li>               <li>1x</li>               <li>1.25x</li>               <li>1.5x</li>               <li>2x</li>             </ul>           </div>           <div class="pv-screen ml">             <i class="iconfont icon-quanping"></i>             <i class="iconfont icon-huanyuan hide"></i>           </div>           <div class="pv-screens ml">             <i class="iconfont icon-shipinquanping"></i>             <i class="iconfont icon-tuichuquanping hide"></i>           </div>         </div>       </div>     </div>   </div> </template> <script> export default {    name: "VamVideo" }; </script> <style scoped> @import "./css/iconfont/iconfont.css"; @import "./css/index.css"; </style> 

样式文件我这里就不展示了,我会在文末给出源码地址。

二、开发逻辑执行文件

最最关键的云服务器提供商部分莫过于逻辑文件了,我这里使用构造函数的方式。

// eslint-disable-next-line no-unused-vars function VamVideo(vp, attrObj, styleObj) {    // 初始化   this.timer = null;   this.disX = 0;   this.disL = 0;   this.isPageFullScreen = false;   // 处理视频属性   for (const key in attrObj) {      if (Object.hasOwnProperty.call(attrObj, key) && key !== "controls") {        $(".video-player").setAttribute(key, attrObj[key]);     }   }   // 处理视频样式   for (const key in styleObj) {      if (Object.hasOwnProperty.call(styleObj, key)) {        $(".video-box").style[`${ key}`] = styleObj[key];       key === "width"         ? (this.vbw = styleObj.width)         : (this.vbw = vp.offsetWidth);       key === "height"         ? (this.vbh = styleObj.height)         : (this.vbh = vp.offsetHeight);     }   }   // 封装获取元素节点   function $(el) {      return document.querySelector(el);   }   // 处理当前时间   function nowTime() {      $(".pv-currentTime").innerHTML = changeTime($(".video-player").currentTime);     let scale = $(".video-player").currentTime / $(".video-player").duration;     let w = $(".pv-bar").offsetWidth - $(".pv-dot").offsetWidth;     $(".pv-dot").style.left = scale * w + "px";     $(".pv-played").style.width = scale * w + "px";   }   // 处理时分秒   function changeTime(iNum) {      let iN = parseInt(iNum);     const iH = toZero(Math.floor(iN / 3600));     const iM = toZero(Math.floor((iN % 3600) / 60));     const iS = toZero(Math.floor(iN % 60));     return iH + ":" + iM + ":" + iS;   }   // 补0   function toZero(num) {      if (num <= 9) {        return "0" + num;     } else {        return "" + num;     }   }   // 元素显示   this.showEl = function (el) {      $(el).style.display = "block";   };   // 元素隐藏   this.hideEl = function (el) {      $(el).style.display = "none";   };   // 动态设置视频宽高   this.setVp = function (w, h) {      const _w = String(w).indexOf("px") != -1 ? w : w + "px";     const _h = String(h).indexOf("px") != -1 ? h : h + "px";     $(".video-player").style.width = _w;     $(".video-player").style.height = _h;     $(".video-box").style.width = _w;     $(".video-box").style.height = _h;     $(".pv-bar").style.width = _w;   };   // 底部控制栏(显示/隐藏)   this.bottomTup = function () {      $(".bottom-tool").style.bottom = "0px";   };   this.bottomTdow = function () {      $(".bottom-tool").style.bottom = "-45px";   };   // 播放/暂停   this.usePlay = function () {      if ($(".video-player").paused) {        $(".video-player").play();       this.hideEl(".icon-bofang");       this.showEl(".icon-zanting");       nowTime();       this.timer = setInterval(nowTime, 1000);     } else {        $(".video-player").pause();       this.showEl(".icon-bofang");       this.hideEl(".icon-zanting");       clearInterval(this.timer);     }   };   this.isplay = function () {      this.usePlay();   };   // 总时长   this.useOnplay = function () {      $(".pv-duration").innerHTML = changeTime($(".video-player").duration);   };   // 播放结束   this.useEnd = function () {      this.showEl(".icon-bofang");     this.hideEl(".icon-zanting");   };   // 静音   this.useVolume = function () {      if ($(".video-player").muted) {        $(".video-player").volume = 1;       this.hideEl(".icon-jingyin");       this.showEl(".icon-yinliang");       $(".video-player").muted = false;     } else {        $(".video-player").volume = 0;       this.showEl(".icon-jingyin");       this.hideEl(".icon-yinliang");       $(".video-player").muted = true;     }   };   // 页面全屏   this.pageFullScreen = function () {      const w = document.documentElement.clientWidth || document.body.clientWidth;     const h =       document.documentElement.clientHeight || document.body.clientHeight;     this.isPageFullScreen = !this.isPageFullScreen;     if (this.isPageFullScreen) {        this.setVp(w, h);       this.hideEl(".icon-quanping");       this.showEl(".icon-huanyuan");       this.hideEl(".pv-screens");     } else {        this.setVp(this.vbw, this.vbh);       this.showEl(".icon-quanping");       this.hideEl(".icon-huanyuan");       this.showEl(".pv-screens");     }   };   // 窗口全屏   this.fullScreen = function () {      const el = $(".video-box");     const isFullscreen =       document.fullScreen ||       document.mozFullScreen ||       document.webkitIsFullScreen;     if (!isFullscreen) {        this.showEl(".icon-tuichuquanping");       this.hideEl(".icon-shipinquanping");       this.hideEl(".pv-screen");       (el.requestFullscreen && el.requestFullscreen()) ||         (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||         (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||         (el.msRequestFullscreen && el.msRequestFullscreen());     } else {        this.showEl(".icon-shipinquanping");       this.hideEl(".icon-tuichuquanping");       this.showEl(".pv-screen");       document.exitFullscreen         ? document.exitFullscreen()         : document.mozCancelFullScreen         ? document.mozCancelFullScreen()         : document.webkitExitFullscreen         ? document.webkitExitFullscreen()         : "";     }   };   // 播放进度条   this.useTime = function (ev) {      let ev1 = ev || window.event;     this.disX = ev1.clientX - $(".pv-dot").offsetLeft;     document.onmousemove = (ev) => {        let ev2 = ev || window.event;       let L = ev2.clientX - this.disX;       if (L < 0) {          L = 0;       } else if (L > $(".pv-bar").offsetWidth - $(".pv-dot").offsetWidth) {          L = $(".pv-bar").offsetWidth - $(".pv-dot").offsetWidth;       }       $(".pv-dot").style.left = L + "px";       let scale = L / ($(".pv-bar").offsetWidth - $(".pv-dot").offsetWidth);       $(".video-player").currentTime = scale * $(".video-player").duration;       nowTime();     };     document.onmouseup = function () {        document.onmousemove = null;     };     return false;   };   // 音量控制   this.useListen = function (ev) {      let ev1 = ev || window.event;     this.disL = ev1.clientX - $(".pv-ol").offsetLeft;     document.onmousemove = (ev) => {        let ev2 = ev || window.event;       let L = ev2.clientX - this.disL;       if (L < 0) {          L = 0;       } else if (L > $(".pv-yl").offsetWidth - $(".pv-ol").offsetWidth) {          L = $(".pv-yl").offsetWidth - $(".pv-ol").offsetWidth;       }       $(".pv-ol").style.left = L + "px";       let scale = L / ($(".pv-yl").offsetWidth - $(".pv-ol").offsetWidth);       $(".pv-bg").style.width = $(".pv-ol").offsetLeft + "px";       if ($(".pv-ol").offsetLeft !== 0) {          this.showEl(".icon-yinliang");         this.hideEl(".icon-jingyin");       } else {          this.showEl(".icon-jingyin");         this.hideEl(".icon-yinliang");       }       $(".video-player").volume = scale;     };     document.onmouseup = function () {        document.onmousemove = null;     };     return false;   };   // 播放速度   this.useSpnum = function (e) {      let ev = e || window.event;     $(".pv-spnum").innerText = ev.target.innerText;     const value = ev.target.innerText.replace("x", "");     $(".video-player").playbackRate = value;   }; } // 导出 export default VamVideo; 

三、整合组件逻辑

开发完UI组件以及逻辑组件了,那我们接下来就是将两者结合起来。

<template>   <div     class="video-box"     @mouseenter="vp.bottomTup()"     @mouseleave="vp.bottomTdow()"   >     <video       class="video-player"       @canplay="vp.useOnplay()"       @ended="vp.useEnd()"       @click="vp.isplay()"     ></video>     <div class="bottom-tool">       <div class="pv-bar">         <div class="pv-played"></div>         <div class="pv-dot" @mousedown="vp.useTime()"></div>       </div>       <div class="pv-controls">         <div class="pc-con-l">           <div class="play-btn" @click="vp.usePlay()">             <i class="iconfont icon-bofang"></i>             <i class="iconfont icon-zanting hide"></i>           </div>           <div class="pv-time">             <span class="pv-currentTime">00:00:00</span>             <span>/</span>             <span class="pv-duration">00:00:00</span>           </div>         </div>         <div class="pc-con-r">           <div class="pv-listen ml">             <div class="pv-yl">               <p class="pv-ol" @mousedown="vp.useListen()"></p>               <p class="pv-bg"></p>             </div>             <div class="pv-iconyl" @click="vp.useVolume()">               <i class="iconfont icon-yinliang"></i>               <i class="iconfont icon-jingyin hide"></i>             </div>           </div>           <div class="pv-speed ml">             <p class="pv-spnum">1x</p>             <ul class="selectList" @click="vp.useSpnum()">               <li>0.5x</li>               <li>1x</li>               <li>1.25x</li>               <li>1.5x</li>               <li>2x</li>             </ul>           </div>           <div class="pv-screen ml" @click="vp.pageFullScreen()">             <i class="iconfont icon-quanping"></i>             <i class="iconfont icon-huanyuan hide"></i>           </div>           <div class="pv-screens ml" @click="vp.fullScreen()">             <i class="iconfont icon-shipinquanping"></i>             <i class="iconfont icon-tuichuquanping hide"></i>           </div>         </div>       </div>     </div>   </div> </template> <script> import VamVideo from "./vp.js"; export default {    name: "VamVideo",   data: () => ({      vp: null,     defaultStyle: {        width: "1200px",       height: "600px",     },   }),   props: {      properties: {        type: Object,     },     videoStyle: {        type: Object,     },   },   mounted() {      this.vp = new VamVideo(       document.querySelector(".video-box"),       this.properties,       Object.keys(this.videoStyle).length === 0         ? this.defaultStyle         : this.videoStyle     );   }, }; </script> <style scoped> @import "./css/iconfont/iconfont.css"; @import "./css/index.css"; </style> 

首先我们引入了之前开发完成的逻辑文件vp.js,然后在mounted方法中对类VamVideo进行实例化,赋给this.vp。传给类的几个参数分别是最外层节点、视频属性、视屏样式。props属性中的properties为视频属性,videoStyle为视频样式。

四、发布组件

完成了以上几个步骤的开发,我们需要将我们完成的组件发布到Npm上。

1. 初始化

创建一个空文件夹,我们可以取名叫v-vamvideo。在此文件夹下键入命令:

npm init -y 

因为我们还需要修改,所以直接创建package.json文件。

{    "name": "vue-vam-video",   "version": "1.0.0",   "description": "Vue.js Custom video components",   "main": "index.js",   "author": "maomincoding",   "keywords": ["video"],   "license": "ISC",   "private": false }  name:组件名 author:Npm用户名 main:入口文件 version:版本号,更新组件需要用到这个字段 description:描述 license的值按照以上即可 keywords为:搜索的关键词 private设为false, 开源因此需要将这个字段改为false

2. 引入组件

将我们之前封装好的组件复制到v-vamvide这个文件夹中,高防服务器下图就是我们之前封装好的组件文件目录。

3. 创建入口文件

我们要发布到Npm上需要一个入口文件,我们在v-vamvide根目录下创建一个入口文件,我们这里叫做index.js。

// 引入组件 import VamVideo from "./VamVideo/vamvideo.vue"; // 组件需要添加name属性,代表注册的组件名称 VamVideo.install = (Vue) => Vue.component(VamVideo.name, VamVideo); //注册组件 export default VamVideo; 

4. 创建一个说明文档

发布到Npm上,用户需要知道这个组件干什么的?怎么用?我们在v-vamvide根目录下创建一个说明文档,取名为README.md

# vue-vamvideo > Vue.js Custom video components ## Using documents 1. Introducing components 2. configuration parameter - `properties`: Video properties. - `videoStyle`: Video style. These two parameters need to be set separately. *** <template>   <div id="app">     <vam-video :properties="videoOption.properties" :videoStyle="videoOption.videoStyle"></vam-video>   </div> </template> <script> export default {    name: "Index",   data: () => ({      videoOption: {        properties: {          poster: require("./img/bg.png"),         src:           "https://mos-vod-drcn.dbankcdn.cn/P_VT/video_injection/A91343E9D/v3/9AB0A7921049102362779584128/MP4Mix_H.264_1920x1080_6000_HEAAC1_PVC_NoCut.mp4",         preload: "auto",         loop: "loop",         // autoplay:"autoplay",         // muted:true,         // controls:"controls"       },       videoStyle: {          // width: "1200px",         // height: "600px",       },     },   }) }; </script> *** 

 我们离成功很近了,所以谢谢你可以阅读到这。源码地址:https://github.com/maomincoding/vue-vam-video

5. 发布

开始操作以下步骤之前,你需要把命令行切换到项目根目录下(也就是这里的v-vamvide这个文件夹)。

1.查看登录源是否是http://registry.npmjs.org

npm config get registry 

如果不是,切换登录源。

npm config set registry=http://registry.npmjs.org 

2.登录Npm

npm login 

相继输入用户名、密码、邮箱。回车出现Logged in as maomincoding on http://registry.npmjs.org,那么就登录成功了。

3.上传发布到Npm

npm publish 

 

五、安装组件

既然我们已经发布到Npm上,我们可以去Npm网站上看下效果。

https://www.npmjs.com/package/vue-vam-video

发布组件成功了,那么我们放在Vue工程上测试一下。

1.安装组件

npm i vue-vam-video 

2.注册组件

全局注册

import Vue from vue import App from ./App.vue // 全局注册 import VamVideo from "vue-vam-video"; Vue.use(VamVideo); Vue.config.productionTip = false new Vue({    render: h => h(App), }).$mount(#app)  <template>   <div id="app">     <vam-video :properties="videoOption.properties" :videoStyle="videoOption.videoStyle"></vam-video>   </div> </template> <script> export default {    name: "App",   data: () => ({      videoOption: {        properties: {          poster: require("./assets/logo.png"),         src:           "https://mos-vod-drcn.dbankcdn.cn/P_VT/video_injection/A91343E9D/v3/9AB0A7921049102362779584128/MP4Mix_H.264_1920x1080_6000_HEAAC1_PVC_NoCut.mp4",         preload: "auto",         loop: "loop",         // autoplay:"autoplay",         // muted:true,         // controls:"controls"       },       videoStyle: {          // width: "1200px",         // height: "600px",       },     },   }) }; </script> 

局部注册

<template>   <div id="app">     <vam-video :properties="videoOption.properties" :videoStyle="videoOption.videoStyle"></vam-video>   </div> </template> <script> import VamVideo from vue-vam-video export default {    name: "App",   data: () => ({      videoOption: {        properties: {          poster: require("./assets/logo.png"),         src:           "https://mos-vod-drcn.dbankcdn.cn/P_VT/video_injection/A91343E9D/v3/9AB0A7921049102362779584128/MP4Mix_H.264_1920x1080_6000_HEAAC1_PVC_NoCut.mp4",         preload: "auto",         loop: "loop",         // autoplay:"autoplay",         // muted:true,         // controls:"controls"       },       videoStyle: {          // width: "1200px",         // height: "600px",       },     },   }),   components: {      VamVideo   }, }; </script> 

3.效果 大功告成!

云南idc服务商
数据库
上一篇:5、企业注册国内域名需要证件,其它情况一律不需要证件。
下一篇:个人域名转为公司需要什么条件?个人域名转为公司该怎么做?