用HTML5实现一个播放器

您所在的位置:网站首页 播放wrap 用HTML5实现一个播放器

用HTML5实现一个播放器

#用HTML5实现一个播放器| 来源: 网络整理| 查看: 265

先看看最终效果

msedge_7oinBoqqSb.gif

页面实现 HTML

就这俩元素就够了,现在大多数播放器禁止自动播放,所以autoplay属性基本无效

.wrap包裹整个页面,里面通过伪元素实现背景

CSS :root { --margin: 20px; --height: 40px; --src: url(https://tse1-mm.cn.bing.net/th/id/OIP-C.OsuHeUeUgSNozCxofEpIHQC7Es?pid=ImgDet&rs=1); } * { margin: 0; padding: 0; } body { background-color: #000; color: #777; font-size: 14px; text-align: center; } ul { list-style: none; }

基础的重置样式,body设置字体样式,让子元素继承

audio { width: 100%; height: var(--height); opacity: .8; } .wrap { position: relative; /* 减去播放条和自身的margin */ height: calc(100vh - var(--height) - var(--margin)); overflow: hidden; margin-top: var(--margin); }

image.png

接下来加上背景图片

.wrap::before { position: absolute; left: 0; top: 0; width: 100%; height: 100%; opacity: .4; content: ""; background: var(--src) no-repeat center bottom; background-size: contain; }

image.png

再加个背景模糊效果,为了展示才设置.lrc-list高度的,后面要去掉,让他自动撑开

.lrc-list { transition: .6s; height: calc(100vh - var(--height) - var(--margin)); backdrop-filter: blur(5px); } li { height: 30px; line-height: 30px; transition: .6s; } .is-playing { transform: scale(1.22); color: #fff; }

image.png

JS 歌词

首先就是歌词部分,我到网上下载了一段歌词文件

const lrc = `[00:31.65] 作词:周杰伦 作曲:周杰伦 [00:01.65] [00:31.86]古巴比伦王颁布了汉摩拉比法典 `;

首先,观察他的特点

每一行歌词,以换行结尾 ]分割了每一行歌词和时间的位置

那么接下来就是用合理的数据结构存储歌词了

先明确一下,我们能获取什么信息

播放的时候,audio元素,提供timeupdate时间,当时间变化时触发

这时可以获取audio.currentTime,也就是现在播放的时间

数据结构

经过分析,那么现在可以选择数组里放入对象存储 顺序按照歌词时间 const lrc = [ { word: '...', time: ... } ]

这样就能描述每一份歌词了

接下来就是实现了

function parseLrc() { const lrc = `[00:31.65] 作词:周杰伦 作曲:周杰伦 [00:01.65] [00:31.86]古巴比伦王颁布了汉摩拉比法典 `; const res = []; lrcArr = lrc.split('\n'); lrcArr.forEach((lrcDetail, index) => { const lrc = lrcDetail.split(']'), time = parseTime(lrc[0].slice(1).trim()), word = lrc[1].trim(); res[index] = { time, word }; }); console.log(res) return res; }

根据换行分割成数组,遍历他,这里换成return map是一样的

再根据]分割时间和歌词

时间需要把他解析成秒

function parseTime(timeStr) { const timeArr = timeStr.split(':'); return numFixed(+timeArr[0] * 60 + +timeArr[1]); } function numFixed(num, dec = 2) { return Math.round(num * 10 ** dec) / 10 ** dec; }

因为toFixed部分情况不准,所以我自己写了四舍五入的函数

以num = 3.105为例,四舍五入两位,结果应该是3.11才对

image.png

使用我的函数就是3.105 * 100 = 310.5,再四舍五入就是311,然后除回去100 = 3.11

处理后的结果

image.png

获取数据

const lrc = parseLrc(), oAudio = document.getElementsByTagName('audio')[0], oUl = document.getElementsByClassName('lrc-list')[0], wrapHeight = document.getElementsByClassName('wrap')[0].offsetHeight; let oLis = [], showLrc = false, liHeight = 0, maxHeight = 0;

接下来把歌词添加到ul,并获取各项参数

function addLrc() { const oFrag = document.createDocumentFragment(); for (let i = 0; i < lrc.length; i++) { const li = document.createElement('li'); li.innerText = lrc[i].word; oFrag.appendChild(li); } oUl.appendChild(oFrag); oLis = oUl.children; // 歌词列表高度 - 外包装高度 用来判断播放完毕 maxHeight = oUl.offsetHeight - wrapHeight; liHeight = oLis[0].offsetHeight; }

image.png

基础布局就实现了

事件处理

现在要在播放时处理歌词滚动

oAudio.addEventListener('timeupdate', e => { const curTime = oAudio.currentTime; document.getElementsByClassName('is-playing')[0]?.classList.toggle('is-playing'); transformLrc(curTime); }); function transformLrc(curTime) { let index = getLrcIndex(curTime), offsetY = liHeight / 2 + liHeight * index - wrapHeight / 2; if (offsetY < 0) offsetY = 0; if (offsetY > maxHeight) offsetY = maxHeight; oLis[index].classList.toggle('is-playing'); oUl.style.transform = `translateY(${-offsetY}px)`; } function getLrcIndex(curTime) { let index; for (let i = 0; i < lrc.length; i++) { if (lrc[i].time > curTime) { index = i - 1; if (index < 0) return 0; return index; } }; const len = lrc.length - 1; if (curTime > lrc[len].time) return len; }

getLrcIndex根据时间遍历数组,找到第一个比他大的对象,再减一使用上一个

offsetY根据每行歌词高度,乘以索引,再减去一半居中

减去wrapHeight / 2是为了在屏幕居中

每次切换歌词时,给对应的歌词那一行元素,加上播放类,切换显示

至此,基本功能全部完成

锦上添花

window.addEventListener('click', () => { oUl.style.opacity = showLrc ? 1 : 0; showLrc = !showLrc; }); window.addEventListener('keyup', (e) => { if (e.code === 'Space') { e.preventDefault() oAudio.paused ? oAudio.play() : oAudio.pause(); } }); window.addEventListener('keydown', (e) => { // 阻止按键造成页面滚动 if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Space'].includes(e.code)) { e.preventDefault(); } });

添加点击页面隐藏歌词,空格键暂停播放事件

msedge_7oinBoqqSb.gif



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3