zoukankan      html  css  js  c++  java
  • ts 实现简单的video播放器 源码: https://github.com/yuhualiang/miProjectTwo

    let { default: styles } = require('./video.css')
    
    
    interface IComponent {
      templateContainer: HTMLElement;
      init: () => void;
      template: () => void;
      handle: () => void;
    }
    
    interface IOption {
      ele: string | HTMLElement;
      url: string;
      height?: string;
      width?: string;
      autoplay?: boolean;
      poster?: string;
    }
    
    
    class Video implements IComponent {
      templateContainer;
      constructor(private settings: IOption) {
        this.settings = Object.assign({
          height: '100%',
           '100%',
          autoplay: false
        }, settings)
    
        this.init()
      }
      init() {
        this.template()
        this.handle()
      }
      template() {
        this.templateContainer = document.createElement('div')
        this.templateContainer.className = styles.video
        this.templateContainer.style.width = this.settings.width
        this.templateContainer.style.height = this.settings.height
        this.templateContainer.innerHTML = `
          <video class="${styles['video-content']}" src="${this.settings.url}"></video>
          <div class="${styles['video-content-play']}">
          <i class="iconfont iconplay"></i>
          </div>
          <div class="${styles['video-controls']}">
            <div class="${styles['video-progress']}">
              <div class="${styles['video-progress-now']}"></div>
              <div class="${styles['video-progress-suc']}"></div>
              <div class="${styles['video-progress-bar']}"></div>
              <div class="${styles['video-progress-track']}"></div>
            </div>
            <div class="${styles['video-play']}">
              <i class="iconfont icon-iconplay"></i>
            </div>
            <div class="${styles['video-time']}">
              <span>00:00</span> / <span>00:00</span>
            </div>
            <div class="${styles['video-full']}">
              <i class="iconfont iconfullscreen"></i>          
            </div>
            <div class="${styles['video-volume']}">
              <i class="iconfont iconvolume"></i>
              <div class="${styles['video-volprogress']}">
                <div class="${styles['video-volprogress-now']}"></div>
                <div class="${styles['video-volprogress-bar']}"></div>
              </div>
            </div>
          </div>
        `
    
        if (typeof this.settings.ele === 'object') {
          this.settings.ele.appendChild(this.templateContainer)
        } else {
          document.querySelector(`.${this.settings.ele}`).appendChild(this.templateContainer)
        }
        if (this.settings.poster) {
          let videoNode: HTMLVideoElement = this.templateContainer.querySelector('video')
          videoNode.setAttribute('poster', this.settings.poster)
        }
      }
      handle() {
        let timer;
        let videoContent: HTMLVideoElement = this.templateContainer.querySelector(`.${styles['video-content']}`)
        let videoControls: HTMLElement = this.templateContainer.querySelector(`.${styles['video-controls']}`)
        let videoProgress = this.templateContainer.querySelectorAll(`.${styles['video-progress']} div`)
        let videoTime = this.templateContainer.querySelectorAll(`.${styles['video-time']} span`)
        let videoPlay = this.templateContainer.querySelector(`.${styles['video-play']} i`)
        let videoContentPlay = this.templateContainer.querySelector(`.${styles['video-content-play']} i`)
        let videoVolume = this.templateContainer.querySelectorAll(`.${styles['video-volprogress']} div`)
        let videoVolumeIcon: HTMLElement = this.templateContainer.querySelector(`.${styles['video-volume']} i`)
        let videoVolumeScale: number = 0.5;
        videoVolumeIcon.style.cursor = 'pointer'
        let videoFullScreen = this.templateContainer.querySelector(`.${styles['video-full']} i`)
        if (this.settings.autoplay) {
          timer = setInterval(playing, 1000)
          videoContent.play()
          videoContent.volume = videoVolumeScale
        }
    
        videoContent.addEventListener('canplay', () => {
          videoTime[1].innerHTML = formatTime(videoContent.duration)
        })
        videoContent.addEventListener('play', () => {
          videoPlay.className = 'iconfont iconpause'
          videoContentPlay.parentNode.style.display = 'none'
          timer = setInterval(playing, 1000)
        });
        videoContent.addEventListener('ended', (event) => {
          videoContentPlay.parentNode.style.display = 'block'
          clearInterval(timer)
        })
        videoContent.addEventListener('pause', () => {
          videoPlay.className = 'iconfont iconplay'
          videoContentPlay.parentNode.style.display = 'block'
          clearInterval(timer)
        });
        videoPlay.addEventListener('click', (e: MouseEvent) => {
          if (videoContent.paused) {
            videoContent.play()
          }
          else {
            videoContent.pause()
          }
          e.preventDefault()
          e.stopPropagation()
        })
        videoContentPlay.addEventListener('click', () => {
          videoPlay.click()
        })
        // 播放进度的控制
        videoProgress[2].addEventListener('mousedown', function (e: MouseEvent) {
          let downX = e.pageX // 按下点的x坐标
          let downL = this.offsetLeft // 到当前有定位的父元素节点的左偏移
    
          document.onmousemove = (ev: MouseEvent) => {
            let scale = (ev.pageX - downX + downL + 8) / this.parentNode.offsetWidth;
            changeVideoProgress(scale)
          }
          document.onmouseup = () => {
            document.onmousemove = document.onmouseup = null
          }
          e.preventDefault()
        })
        videoProgress[3].addEventListener('click', function (e: MouseEvent) {
          let scale = e.offsetX / this.parentNode.offsetWidth
          changeVideoProgress(scale)
        })
        // 音量的控制
        videoVolume[1].addEventListener('mousedown', function (e: MouseEvent) {
          let downX = e.pageX // 按下点的x坐标
          let downL = this.offsetLeft + 7 // 到当前有定位的父节点的左偏移
          document.onmousemove = (ev: MouseEvent) => {
            let pageX = ev.pageX
            videoVolumeScale = (pageX - downX + downL) / this.parentNode.offsetWidth
            videoVolumeScale > 1 && (videoVolumeScale = 1)
            if (videoVolumeScale <= 0) {
              videoVolumeScale = 0
              videoVolumeIcon.className = 'iconfont iconmute'
            } else {
              videoVolumeIcon.className = 'iconfont iconvolume'
            }
            this.style.left = videoVolumeScale * 100 + '%'
            videoVolume[0].style.width = videoVolumeScale * 100 + '%'
            videoContent.volume = videoVolumeScale
          }
          document.onmouseup = () => {
            document.onmousemove = document.onmouseup = null
          }
          e.preventDefault()
        })
        // 静音操作
        videoVolumeIcon.addEventListener('click', function (e) {
          if (videoContent.volume > 0) {
            videoContent.volume = 0
            this.className = 'iconfont iconmute'
          } else {
            this.className = 'iconfont iconvolume'
            videoContent.volume = videoVolumeScale
          }
          e.preventDefault()
        })
        // 全屏操作
        videoFullScreen.addEventListener('click', function (e: MouseEvent) {
          videoContent.requestFullscreen()
        })
        this.templateContainer.addEventListener('mouseenter', (e: MouseEvent) => {
          videoControls.style.bottom = 0 + 'px'
        })
        this.templateContainer.addEventListener('mouseleave', (e: MouseEvent) => {
          videoControls.style.bottom = -50 + 'px'
        })
        // 点击视频区域改变播放状态
        videoContent.addEventListener('click', (e: MouseEvent) => {
          if (videoContent.paused) {
            videoContent.play()
          } else {
            videoContent.pause()
          }
          e.preventDefault()
          e.stopPropagation()
        })
        function playing() {
          let scale = videoContent.currentTime / videoContent.duration
          let scaleSuc = videoContent.buffered.end(0) / videoContent.duration;
          videoProgress[0].style.width = scale * 100 + '%';
          videoProgress[1].style.width = scaleSuc * 100 + '%';
          videoProgress[2].style.left = scale * 100 + '%';
          videoTime[0].innerHTML = formatTime(videoContent.currentTime)
        }
        function changeVideoProgress(scale) {
          scale < 0 && (scale = 0);
          scale > 1 && (scale = 1);
    
          videoProgress[0].style.width = scale * 100 + '%'
          videoProgress[1].style.width = scale * 100 + '%'
          videoProgress[2].style.left = scale * 100 + '%'
          videoContent.currentTime = scale * videoContent.duration
          videoContent.paused && videoContent.play()
        }
    
        function formatTime(number: number): string {
          number = Math.round(number);
          let min = Math.floor(number / 60);
          let sec = Math.floor(number % 60);
          return setZero(min) + ':' + setZero(sec);
        }
        function setZero(number: number): string {
          if (number < 10) {
            return '0' + number;
          }
          return '' + number;
        }
      }
    }
    function video(option: IOption) {
      return new Video(option)
    }
    
    
    export default video
    .video {
      position: relative;
      overflow: hidden;
    }
    
    .video-content {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    
    .video-controls {
      position: absolute;
      width: 100%;
      bottom: -50px;
      left: 0;
      height: 50px;
      background-color: rgba(0, 0, 0, 0.8);
      transition: 0.5s;
    }
    
    .video-progress {
      position: relative;
      width: 100%;
      height: 5px;
      background-color: #222223;
    }
    
    .video-progress-now {
      width: 0;
      height: 100%;
      background: #ff6a03;
      position: absolute;
      left: 0;
      z-index: 1;
    }
    
    .video-progress-suc {
      width: 0;
      height: 100%;
      background: #666;
      position: absolute;
      left: 0;
    }
    
    .video-progress-bar {
      width: 14px;
      height: 14px;
      background: white;
      border-radius: 50%;
      position: absolute;
      left: 0;
      top: 0;
      margin-left: -7px;
      margin-top: -5px;
      z-index: 2;
      cursor: pointer;
      z-index: 12;
    }
    
    .video-progress-track {
      height: 9px;
      width: 100%;
      position: absolute;
      left: 0;
      top: -2px;
      z-index: 11;
    }
    
    .video-progress-now {
      width: 0;
      height: 100%;
      background: #ff6a03;
      position: absolute;
      left: 0;
      z-index: 1;
    }
    
    .video-play {
      float: left;
      height: 45px;
      line-height: 45px;
      margin-left: 35px;
      cursor: pointer;
    }
    
    .video-play i {
      color: #fff;
      font-size: 20px;
    }
    
    .video-content-play {
      width: 50px;
      height: 50px;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      cursor: pointer;
    }
    
    .video-content-play i {
      color: #fff;
      font-size: 30px;
    }
    
    .video-time {
      float: left;
      height: 45px;
      line-height: 45px;
      margin-left: 30px;
      color: #fff;
    }
    
    .video-full {
      float: right;
      height: 45px;
      line-height: 45px;
      margin-right: 20px;
    }
    
    .video-full i {
      font-size: 20px;
      color: #fff;
      cursor: pointer;
    }
    
    .video-volume {
      float: right;
      display: flex;
      align-items: center;
      margin-right: 30px;
      height: 45px;
    }
    
    .video-volume i {
      font-size: 20px;
      color: white;
      margin-right: 20px;
    }
    
    .video-volprogress {
      width: 100px;
      height: 5px;
      background: #222223;
      position: relative;
    }
    
    .video-volprogress-now {
      width: 50%;
      height: 100%;
      background: #ff6a03;
    }
    
    .video-volprogress-bar {
      height: 14px;
      width: 14px;
      background: #fff;
      border-radius: 50%;
      position: absolute;
      left: 50%;
      top: 0;
      margin-left: -7px;
      margin-top: -5px;
      z-index: 2;
      cursor: pointer;
    }
  • 相关阅读:
    前端环境搭建
    mybatis
    An internal error occurred during: "Launching on Tomcat 7.x"
    mybatis批量添加、批量删除
    linux系统下怎么关闭一个端口
    httpclient传参类型与响应参数接收
    scheduled定时任务cron表达式知识地址
    ClassNotFoundException: http.nio.NHttpClientEventHandle
    发送请求工具—Advanced REST Client的安装使用
    linux下Tomcat配置提示权限不够解决办法
  • 原文地址:https://www.cnblogs.com/ladybug7/p/14127889.html
Copyright © 2011-2022 走看看