zoukankan      html  css  js  c++  java
  • 手把手从零开始---封装一个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, //跟随外层容器变化大小,跟随的是外层宽度
                 "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‘
    • 视频容器的宽度, 字符串或数字 单位像素
    • 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="{'100%',position:'relative',height:height}">
        <div data-vjs-player style="100%">
          <video ref="videoNode" class="video-js vjs-default-skin vjs-big-play-centered">抱歉,您的浏览器不支持</video>
        </div>
        <div
          v-if="loading"
          :style="{'100%',height:height,position:'absolute',left:'0px',top:'0px'}"
        >
          <img
            :style="{'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: {
        // 标记点样式
         "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="{'100%',position:'relative',height:height}">
        <div data-vjs-player style="100%">
          <video ref="videoNode" class="video-js vjs-default-skin vjs-big-play-centered">抱歉,您的浏览器不支持</video>
        </div>
        <div
          v-if="loading"
          :style="{'100%',height:height,position:'absolute',left:'0px',top:'0px'}"
        >
          <img
            :style="{'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, //跟随外层容器变化大小,跟随的是外层宽度
             "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: {
                // 标记样式
                 "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.js中使用Stylus预处理器
    前端面试问题(JavaScript)
    前端面试问题(CSS3)
    前端面试问题(HTML5+Http+web)
    VUE2中文文档:组件基础篇
    VUE2中文文档:语法基础笔记
    transition动画效果初识(实例)
    Centos5.2升级openssh7.4p1
    解决python升级导致pip无法使用
    使用jenkins时因为脚本权限问题执行项目失败
  • 原文地址:https://www.cnblogs.com/monkeySoft/p/13292943.html
Copyright © 2011-2022 走看看