首页 > 其他 > 详细

ts 实现简单的video播放器

时间:2020-12-13 11:56:51      阅读:33      评论:0      收藏:0      [点我收藏+]
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%‘,
      width: ‘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;
}

 

ts 实现简单的video播放器

原文:https://www.cnblogs.com/ladybug7/p/14127889.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!