PC端使用video.js

629 阅读1分钟

PC端使用video.js点击播放按钮 弹出遮罩层播放

import React, { useState, useRef, useLayoutEffect } from 'react';
import { Modal } from '@antd/design'; 
import 'video.js/dist/video-js.css';
import videojs from 'video.js';
import './index.scss';

function videoInit(id, options) {
  const player = videojs(id, options, function onPlayerReady() {
    videojs.log('Your player is ready! 111');

    this.on('abort', () => {
      videojs.log('abort');
    });
    this.on('play', () => {
      videojs.log('play');
    });
    this.on('suspend', () => {
      videojs.log('suspend');
    });
    this.on('emptied', () => {
      videojs.log('emptied');
    });
    this.on('stalled', () => {
      videojs.log('stalled');
    });
    this.on('pause', () => {
      videojs.log('pause');
    });
    this.on('canplay', () => {
      videojs.log('canplay');
    });
    this.on('playing', () => {
      videojs.log('playing');
    });
    this.on('seeking', () => {
      videojs.log('seeking');
    });
    this.on('seeked', () => {
      videojs.log('seeked');
    });
    this.on('canplay', () => {
      videojs.log('canplay');
      // In this context, `this` is the player that was created by Video.js.
      // this.play();
    });
    this.on('loadeddata', () => {
      videojs.log('loadeddata');
      // In this context, `this` is the player that was created by Video.js.
    });

    // How about an event listener?
    this.on('ended', () => {
      videojs.log('Awww...over so soon?!');
    });
  });
  return player;
}

interface IProps {
  id: string; // 视频唯一id,用于获取dom节点播放视频
  poster: string; // 视频封面url,视频未播放时展示的图片
  videoMp4Url?: string; // mp4格式视频url
  videoOggUrl?: string; // mp4格式视频url
  videoWebmUrl?: string; // mp4格式视频url
  children: JSX.Element | JSX.Element[];
  clickPlayStartCallBack?: Function; // 点击播放时回调函数;
}

export default function VideoPlayer(props: IProps) {
  const { id, poster, videoMp4Url, videoOggUrl, videoWebmUrl, children, clickPlayStartCallBack } = props;
  const [isShowModal, setIsShowModal] = useState<boolean>(false);
  const idVideo = `${id}-video`;
  const videoPlayerRef = useRef();
  // const isInIos = isIos();
  const options = {};

  useLayoutEffect(() => {
    if (!isShowModal || videoPlayerRef?.current) {
      return;
    }
    setTimeout(() => {
      videoPlayerRef.current = videoInit(idVideo, options);
    }, 10);
  }, [isShowModal]);

  /** ios 渲染隐藏的视频, 会打开 ios 默认的视频播放弹窗 */
  const renderVideo = () => (
    <video
      id={idVideo}
      className="video-js"
      // autoPlay
      controls
      preload="auto"
      poster={poster}
      data-setup="{}"
      disablePictureInPicture
    >
      {videoMp4Url ? <source src={videoMp4Url} type="video/mp4" /> : null}
      {videoOggUrl ? <source src={videoOggUrl} type="video/ogg" /> : null}
      {videoWebmUrl ? <source src={videoWebmUrl} type="video/webm" /> : null}
      <track kind="captions" />
      <p className="vjs-no-js">
        To view this video please enable JavaScript, and consider upgrading to a web browser that
        <a href="http://videojs.com/html5-video-support/" target="_blank" rel="noreferrer">
          supports HTML5 video
        </a>
      </p>
    </video>
  );

  const playVideo = () => {
    setIsShowModal(true);
    if (videoMp4Url || videoOggUrl || videoWebmUrl) {
      setTimeout(() => {
        const domId = document.getElementById(`${idVideo}_html5_api`) || document.getElementById(`${idVideo}`);
        if (domId) (domId as HTMLVideoElement).play();
      }, 50);
    }
    clickPlayStartCallBack && clickPlayStartCallBack();
  };
  return (
    <div className="zp_videoPlayer">
      <div className="videoImgWrap" id={id} onClick={() => playVideo()}>
        {children}
      </div>
      {isShowModal && (
        <Modal
          className="zp_videoPlayer_modal"
          mask
          maskClosable
          closable={false}
          onClose={() => {
            setIsShowModal(false);
          }}
        >
          <Modal.Body>
            <i
              className="iconfont-official-website icon-zp-mtdui-close closeIcon cursor_pointer"
              onClick={() => {
                setIsShowModal(false);
              }}
            />
            {renderVideo()}
          </Modal.Body>
        </Modal>
      )}
    </div>
  );
}

.zp_videoPlayer {
  width: 100%;
  height: 100%;
  .videoImgWrap {
    width: 100%;
    height: 100%;
  }
}
.zp_videoPlayer_modal {
  min-width: 890px;
  .video-js {
    width: 890px;
    height: 500px;
    // .vjs-big-play-button {
    //   width: 34px;
    //   height: 34px;
    //   border: none;
    //   border-radius: 50%;
    //   line-height: 34px;
    //   bottom: 10px;
    //   top: auto;
    // }
    .vjs-time-tooltip {
      width: 50px;
    }
  }
  .mtd-mobile-modal-content {
    width: 100%;
    overflow: visible;
  }
  .mtd-mobile-modal-mask-bg {
    background-color: rgba(0, 0, 0, 0.7);
  }
  .closeIcon {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 20;
    border: 10px solid transparent;
    font-size: 20px;
    font-weight: bolder;
    color: white;
  }
}
.zp_videoPlayer_modal.mtd-modal {
  padding: 0;
  .mtd-modal-body {
    padding: 0;
  }
  .mtd-modal-header {
    display: none;
  }
}

在组件中使用

 <div className="item_img_wrapper">
    <VideoPlayer id={v.code} poster={v.poster} videoMp4Url={v.linkUrl}>
      <img style={{ width: '100%', height: '100%' }} alt="cover" src={v.poster} />
      <div className="play_btn">
        <img src={require('../../../imgs/play.svg')} alt="" />
      </div>
      <div className="time_btn">
        <div className="mins">{v.duration}</div>
        <div className="date">{v.date}</div>
      </div>
    </VideoPlayer>
 </div>