TypeScript封装video播放器组件
通过之前对 TypeScript 的学习,今天我们用它封装一个播放器组件,希望大家喜欢,最后我会放上 GitHub 地址,需要的话可以下载下来学习。
Popup 弹层组件开发
主要是 Popup 弹层组件框架搭建、模块化、弹层布局结构及样式、遮罩层布局及样式、弹层交互及弹层容器回调实现。
// import './popup.css'; // 全局 css 操作 let styles = require('./popup.css'); // import styles from './popup.css' interface Ipopup { width? : string; height? : string; title? : string; pos? : string; mask? : boolean; content? : (content : HTMLElement) => void; } interface Icomponent { tempContainer : HTMLElement; init : () => void; template : () => void; handle : () => void; } function popup(options : Ipopup) { return new Popup(options); } class Popup implements Icomponent{ tempContainer; mask; constructor(private settings : Ipopup) { this.settings = Object.assign({ width: '100%', height: '100%', title: '', pos : 'center', // 弹窗位置 left right center mask: true, // 是否显示遮罩 content: function(){} },this.settings); this.init(); } // 初始化 init(){ this.template(); this.settings.mask && this.createMask(); this.handle(); this.contentCallback(); } // 创建模板' template(){ this.tempContainer = document.createElement('div'); this.tempContainer.style.width = this.settings.width; this.tempContainer.style.height = this.settings.height; this.tempContainer.className = styles.popup; this.tempContainer.innerHTML = ` <div class="${styles['popup-title']}"> <h3>${ this.settings.title }</h3> <i class="iconfont icon-baseline-close-px"></i> </div> <div class="${styles['popup-content']}"></div> `; document.body.appendChild(this.tempContainer); if (this.settings.pos === 'left') { this.tempContainer.style.left = 0; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'; } else if (this.settings.pos === 'right') { this.tempContainer.style.right = 0; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight)/2 + 'px'; } else { this.tempContainer.style.left = (window.innerWidth - this.tempContainer.offsetWidth)/2 + 'px'; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight)/2 + 'px'; } } // 事件操作 handle(){ let popupClose = this.tempContainer.querySelector(`.${styles['popup-title']} i`); popupClose.addEventListener('click',() => { document.body.removeChild(this.tempContainer); this.settings.mask && document.body.removeChild(this.mask); }); } createMask () { this.mask = document.createElement('div'); this.mask.className = styles.mask; this.mask.style.width = '100%'; this.mask.style.height = document.body.offsetHeight + 'px'; document.body.appendChild(this.mask); } contentCallback () { let popupContent = this.tempContainer.querySelector(`.${styles['popup-content']}`); this.settings.content(popupContent); } } export default popup;
弹出层中的 Video 播放器组件开发
主要包含组件框架搭建、播放器布局结构、播放与暂停的实现、当前时间与总时间计算、全屏功能、播放进度条、拖拽播放进度条与音量进度条、配置自动播放等功能的实现。
let styles = require('./video.css'); interface Ivideo { url : string; elem : string | HTMLElement; width? : string; height? : string; autoplay? : boolean; } interface Icomponent { tempContainer : HTMLElement; init : () => void; template : () => void; handle : () => void; } function video(options: Ivideo) { return new Video(options); } class Video implements Icomponent { tempContainer constructor(private settings : Ivideo){ this.settings = Object.assign({ width: '100%', height : '100%', autoplay : false },this.settings); this.init(); } init () { this.template(); this.handle(); } template () { this.tempContainer = document.createElement('div'); this.tempContainer.className = styles.video; this.tempContainer.style.width = this.settings.width; this.tempContainer.style.height = this.settings.height; this.tempContainer.innerHTML =` <video class="${styles['video-content']}" src="${this.settings.url}"></video> <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> <div class="${styles['video-play']}"> <i class="iconfont icon-icon_play"></i> </div> <div class="${styles['video-time']}"> <span>00:00</span> / <span>00:00</span> </div> <div class="${styles['video-full']}"> <i class="iconfont icon-full-screen"></i> </div> <div class="${styles['video-volume']}"> <i class="iconfont icon-yinliang"></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.elem === 'object') { this.settings.elem.appendChild(this.tempContainer); }else { document.querySelector(`${this.settings.elem}`).appendChild(this.tempContainer); } } handle () { let videoContent:HTMLVideoElement = this.tempContainer.querySelector(`.${styles['video-content']}`); let videoControls = this.tempContainer.querySelector(`.${styles['video-controls']}`); let videoPlay = this.tempContainer.querySelector(`.${styles['video-controls']} i`); let videoTimes = this.tempContainer.querySelectorAll(`.${styles['video-time']} span`); let videoFull = this.tempContainer.querySelector(`.${styles['video-full']} i`); let videoProgress = this.tempContainer.querySelectorAll(`.${styles['video-progress']} div`); let videoVolProgress = this.tempContainer.querySelectorAll(`.${styles['video-volprogress']} div`); let timer; videoContent.volume = 0.5; if(this.settings.autoplay){ // 是否进行自动播放处理 timer = setInterval(playing,1000); videoContent.play(); } this.tempContainer.addEventListener('mouseenter',function(){ videoControls.style.bottom = 0; }); this.tempContainer.addEventListener('mouseleave',function(){ videoControls.style.bottom = '-50px'; }) // 视频是否加载完毕 videoContent.addEventListener('canplay',() => { // console.log(videoTimes[1]); videoTimes[1].innerHTML = formatTime(videoContent.duration); }); // 视频播放事件 videoContent.addEventListener('play',() => { videoPlay.className = 'iconfont icon-ziyuan'; timer = setInterval(playing,1000); }); // 视频暂停事件 videoContent.addEventListener('pause',() => { videoPlay.className = 'iconfont icon-icon_play' clearInterval(timer); }); // 播放暂停 videoPlay.addEventListener('click',()=>{ if(videoContent.paused){ videoContent.play(); }else{ videoContent.pause(); } }); // 全屏 videoFull.addEventListener('click',()=>{ videoContent.requestFullscreen(); }); // 视频进度条拖拽事件 videoProgress[2].addEventListener('mousedown',function(ev:MouseEvent){ let downX = ev.pageX; let downL = this.offsetLeft; document.onmousemove = (ev:MouseEvent) => { let scale = (ev.pageX - downX + downL + 8) / this.parentNode.offsetWidth; if (scale < 0){ scale = 0; } else if (scale > 1) { scale = 1; } videoProgress[0].style.width = scale * 100 + '%'; videoProgress[1].style.width = scale * 100 + '%'; this.style.left = scale * 100 + '%'; videoContent.currentTime = scale * videoContent.duration; }; document.onmouseup = () => { document.onmousemove = document.onmouseup = null; }; ev.preventDefault(); }) // 音量控制 videoVolProgress[1].addEventListener('mousedown',function(ev:MouseEvent){ let downX = ev.pageX; let downL = this.offsetLeft; document.onmousemove = (ev:MouseEvent) => { let scale = (ev.pageX - downX + downL + 8) / this.parentNode.offsetWidth; if (scale < 0){ scale = 0; } else if (scale > 1) { scale = 1; } videoVolProgress[0].style.width = scale * 100 + '%'; this.style.left = scale * 100 + '%'; videoContent.volume = scale; }; document.onmouseup = () => { document.onmousemove = document.onmouseup = null; }; ev.preventDefault(); }) function playing() { // 正在播放中 let scale = videoContent.currentTime / videoContent.duration; let scaleSuc = videoContent.buffered.end(0) / videoContent.duration; videoTimes[0].innerHTML = formatTime(videoContent.currentTime); videoProgress[0].style.width = scale * 100 + '%'; videoProgress[1].style.width = scaleSuc * 100 + '%'; videoProgress[2].style.left = scale * 100 + '%'; } // 格式化时间 时分秒 function formatTime(number:number):string { number = Math.round(number); let min = Math.floor(number/60); let sec = number%60; return setZero(min) + ':' + setZero(sec); } // 当时间出现出现个位时,补 0 操作 function setZero(number:number):string{ if(number<10){ return '0' + number; }else{ return '' + number; } } } } export default video;
源码下载GitHub
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » TypeScript封装video播放器组件
码云笔记 » TypeScript封装video播放器组件