基于react的hooks搭建video.js观看视屏并增加相关配置并实时更新和禁止拖动快进和切换视屏倍速配置

由于最近接了个项目里面需要观看视屏记录学分等功能,就想着用video.js来进行观看视屏,但是网上查询用到的都是原生的,这边来增加一个通过react hooks进行观看视屏的配置 ,并展示如何定时器更新并记录观看视屏的进度,并且阻止拖动进度条快进功能⬇️

禁止拖动的关键代码

判断当前看视屏的最大事件 接口获取,如果没有最大进度就为0,每次拖动获取当前时间,如果大于最大2,就表示快进了,回到当前的最大事件,如果不大于,并且当前时间大于最大时间,则把当前最大的时间设置为现在观看的时间

        let maxTime = dataDetail?.view_duration || 0;
         // 监听播放进度事件
          player.on('timeupdate', function () {
            let currentTime = this.currentTime();
            let duration = this.duration();
            if (currentTime - maxTime > 2) {
              this.currentTime(maxTime);
            } else {
              if (currentTime > maxTime) {
                maxTime = this.currentTime();
              }
            }
            //lastProcess为传给后端的进度字段
            //lastProgress = currentTime / duration;
          });

 5秒实时更新的关键代码

videojs中自带ready函数,触发定时器接口更行,挂载intervalHandle是为了在离开页面时取消更新,不然会一直更新下去

       let intervalHandle = useRef();
    
        const player = videojs(
        videoRef.current,
        optiones,   
        function onPlayerReady() {
          intervalHandle.current = setInterval(() => {
            upDateProgress(lastProgress, maxTime);
          }, 5000);
           }

          useEffect(() => {
            return () => {
             clearInterval(intervalHandle.current);
                };
             }, []);

切换视屏观看倍速配置

因为我用的是video.js 8.0 所以有两种办法

1、最简单的 在options中增加 playbackRates: [0.5, 1, 1.5, 2], 属性,注意!老版本只需要增加以上属性,但是8.0还需要在下一层的controlBar中增加{name:'playbackRateMenuButton',}

   let optiones = {
      playbackRates: [0.5, 1, 1.5, 2],
      controlBar: {
        children: [
          {
            name:'playbackRateMenuButton',
          },
        ],
      },
    };

2、第二种是因为一开始我没有用{name:'playbackRateMenuButton'},导致我以为属性不可用了,所以先手写了一套,也是可以使用的

说一下第二种切换倍速的我的思想与代码,在渲染videojs播放器时,插入原生代码并且附带videojs的css,这样可以避免复杂的修改样式,然后再进行onchange事件触发videojs自带的playbackRate属性来进行修改视屏的倍速,但是由于原生代码中的onchange事件不能直接找到react中写的函数,所以我们需要通过监听切换倍速的点击事件来触发我们的函数,这边我们是给select加了个myselect的id,并且addTool要在onPlayerReady函数中触发

  const rateChange=(params) =>{
      console.log(params,'params');
      let myselect = document.getElementById('myselect')
      var index = myselect.selectedIndex
      var selectedValue =myselect.options[index].value
      const player = videojs(videoId)
      player.ready(function() {
        var _this = this
        //速率
        setTimeout(function() {
            _this.playbackRate(Number(selectedValue));
        },20);
    });
      setVideoSpeed(Number(selectedValue))
      console.log(myselect,index,selectedValue,Number(selectedValue),'index');
  }  
const addTool = () => {
    let divSFYX2 = document.createElement('div');
    divSFYX2.innerHTML = `<button class="vjs-control " id="danmu_send_opt"><select id='myselect' style="-webkit-appearance: none;background-color: transparent;border: none;border-radius: 0px" change="rateChange(this.options[this.options.selectedIndex].value)">\n' +
      '  <option value ="1">1.0X</option>\n' +
      '  <option value ="1.25">1.25X</option>\n' +
      '  <option value="1.5">1.5X</option>\n' +
      '  <option value="2.0">2.0X</option>\n' +
      '</select></button>`;
      //监听点击事件来出发切换倍速函数
      divSFYX2.addEventListener('change', (e)=>rateChange(e));
    if (!addTools) {
     //在bar中插入创建的div
      document.querySelector('.vjs-control-bar')?.appendChild(divSFYX2);
      setAddTools(true)
    } else {
      console.log('已经添加了');
    }
  };

下面是完整代码 👇

import { useLocation } from 'react-router';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';
const zh = require('video.js/dist/lang/zh-CN.json');
zh['Picture-in-Picture'] = '画中画';
videojs.addLanguage('zh-CN', zh);


  let intervalHandle = useRef();
  const videoRef = useRef();
//刚进入页面通过接口获取视屏的url
  const [videoUrl, setVideoUrl] = useState('');
//获取看到的视屏的详情(包括进度)
  const [dataDetail, setDataDetail] = useState({});
//state为其他页面穿参,优先级考前,看你当前需求 可以删除
   const { state } = useLocation();

//useEffect中配置video.js
  useEffect(() => {
    let optiones = {
      controls: true,
      autoplay: false, //视频是否自动播放安卓12无效
      preload: 'auto',
      language: 'zh-CN',
      contextmenu: false,
      width: document.body.clientWidth,
      playbackRates: [0.5, 1, 1.5, 2],
      controlBar: {
        // timeDivider: true,//是否显示时间控制条,默认为true
        // remainingTimeDisplay: false,//是否显示剩余时间,默认为true
        // fullscreenToggle: true // 全屏按钮
        children: [
          //自定义
          { name: 'playToggle' }, // 播放按钮
          {
            name: 'volumePanel', // 音量控制
            inline: false, // 不使用水平方式
          },
          { name: 'currentTimeDisplay' }, // 当前已播放时间
          { name: 'durationDisplay' }, // 总时间
          { name: 'progressControl' }, // 播放进度条
          {
            name: 'pictureInPictureToggle', //支持画中画
          },
          {
            name:'playbackRateMenuButton',
          },
          {
            name: 'FullscreenToggle', //支持全屏
          },
        ],
      },
    };
    if (videoUrl) {
      //判断之前开到的最大时间
      let maxTime = state?.watchProgress || dataDetail?.view_duration || 0;
      const player = videojs(
        videoRef.current,
        optiones,
        function onPlayerReady() {
          this.src(videoUrl); //视频url
          this.poster(''); //视频封面图
          // this.landscapeFullscreen(); // github上说解决横屏播放 但是没起作用
          let lastProgress;
         //第二种增加倍速的方法
          // addTool();
          console.log(dataDetail?.view_duration, '123');
          this.currentTime(maxTime);
          // 监听播放进度事件
          player.on('timeupdate', function () {
            let currentTime = this.currentTime();
            let duration = this.duration();
            if (currentTime - maxTime > 2) {
              this.currentTime(maxTime);
            } else {
              if (currentTime > maxTime) {
                maxTime = this.currentTime();
              }
            }
            lastProgress = currentTime / duration;
          });
            //每五秒触发一次更新接口更新看到的视屏进度
          intervalHandle.current = setInterval(() => {
            upDateProgress(lastProgress, maxTime);
          }, 5000);
        },
      );

      return () => {
        //销毁控制视频高度
        if (player) {
          player.dispose();
        }
      };
    }
  }, [videoUrl]);
//离开页面取消更新
  useEffect(() => {
    return () => {
      clearInterval(intervalHandle.current);
    };
  }, []);

   //挂载并且播放视屏
   <div style={{ width: '100%', height: '100%' }} data-vjs-player>
                <video
                  ref={videoRef}
                  id="videoId"
                  className="video-js"
                  playsInline={true}
                ></video>
              </div>

 如果要在进度条展示当前观看时间,需要在css中进行处理

:global{
    .video-js{
        width: 100%;
        height: 100%;
    }
    .video-js .vjs-duration, .vjs-no-flex .vjs-duration {
        display: inline-block;
      }
      .video-js .vjs-current-time, .vjs-no-flex .vjs-current-time {
        display: inline-block;
      
      }
     .ant-tabs-nav::before{
        border-bottom: 0px !important;
     }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值