目录
1.歌词数据data.js:借鉴了网上copy下来的歌词模板
效果图展示:
一.素材准备:
1.歌词数据data.js:借鉴了网上copy下来的歌词模板
const lrc = `
[00:00.000] 作词 : 黄家驹\n
[00:01.000] 作曲 : 黄家驹\n
[00:02.000] 编曲 : Beyond/梁邦彦\n
[00:03.000] 制作人 : Beyond/梁邦彦\n
[00:18.466]今天我 寒夜里看雪飘过\n
[00:25.110]怀着冷却了的心窝漂远方\n
[00:30.950]风雨里追赶 雾里分不清影踪\n
[00:37.229]天空海阔你与我\n
[00:40.291]可会变 (谁没在变)\n
[00:43.440]多少次 迎着冷眼与嘲笑\n
[00:50.050]从没有放弃过心中的理想\n
[00:55.907]一刹那恍惚 若有所失的感觉\n
[01:02.133]不知不觉已变淡\n
[01:05.243]心里爱 (谁明白我)\n
[01:08.801]原谅我这一生不羁放纵爱自由\n
[01:15.799]也会怕有一天会跌倒\n
[01:22.008]背弃了理想 谁人都可以\n
[01:28.276]哪会怕有一天只你共我\n
[01:34.102]\n
[01:42.695]今天我 寒夜里看雪飘过\n
[01:49.284]怀着冷却了的心窝漂远方\n
[01:55.189]风雨里追赶 雾里分不清影踪\n
[02:01.405]天空海阔你与我\n
[02:04.535]可会变 (谁没在变)\n
[02:08.014]原谅我这一生不羁放纵爱自由\n
[02:15.040]也会怕有一天会跌倒\n
[02:21.279]背弃了理想 谁人都可以\n
[02:27.531]哪会怕有一天只你共我\n
[02:33.633]\n
[03:08.454]仍然自由自我 永远高唱我歌\n
[03:15.064]走遍千里\n
[03:19.739]原谅我这一生不羁放纵爱自由\n
[03:26.734]也会怕有一天会跌倒\n
[03:33.005]背弃了理想 谁人都可以\n
[03:39.257]哪会怕有一天只你共我\n
[03:45.496]背弃了理想 谁人都可以\n
[03:51.756]哪会怕有一天只你共我\n
[03:57.201]原谅我这一生不羁放纵爱自由\n
[04:04.204]也会怕有一天会跌倒\n
[04:10.456]背弃了理想 谁人都可以\n
[04:16.647]哪会怕有一天只你共我\n
[04:22.828]\n
[04:31.852] 录音 : Shunichi Yokoi\n
[04:40.876] 混音 : Shunichi Yokoi\n
[04:49.900] 录音室 : Greenbird St./Tokyu Fun St./West Side St.(Tokyo/From Jan/to Apr./1993)\n
[04:58.924] 母带工程师 : Setsu Hisai at Tokyu Fun St.\n[05:07.948] 弦乐 : 桑野圣乐团 (Kuwano Strings)\n
[05:16.972] OP : Amuse Inc. & Fun House Inc.\n[05:25.996] SP : Amuse H.K. Ltd.`
2.图片准备: 设置title效果
3.音频文件准备:
二.html块:
拓展 <audio> 标签属性:
- src:音乐的URL
- preload:预加载
- autoplay:自动播放
- loop:循环播放
- controls:浏览器自带的控制条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
// 设置title
<link rel="shortcut icon" href="./bitbug_favicon.ico" type="image/x-icon">
// 引入css样式文件
<link rel="stylesheet" href="./index.min.css">
</head>
<body>
<audio src="./海阔天空.mp3" controls></audio>
<div class="box">
<ul class="lrc-list">
</ul>
</div>
</body>
// 引入歌词文件
<script src="./data.js"></script>
<script src="./index.js"></script>
</html>
三.设置scss样式:
*{
margin: 0;
padding: 0;
}
body{
background: #000;
color: #999;
text-align: center;
}
audio{
width: 80%;
margin: 30px 0;
}
.box{
height: 420px;
border: 1px solid #fff;
overflow: hidden;
.lrc-list{
list-style: none;
transform: translateY(-0px);
transition: 0.2s;
li{
line-height: 30px;
transition: 0.2s;
}
.active{
color: #fff;
transform: scale(1.5);
}
}
}
四.逻辑js块:
const doms = {
audio: document.querySelector('audio'),
box: document.querySelector('.box'),
lrcEl: document.querySelector('.lrc-list'),
lis:document.querySelectorAll('.lrc-list li')
}
/**
* 解析歌词字符串
* 得到歌词字符串数组
* {time:时间,words:歌词内容}
*/
function parseLrc() {
const lines = lrc.split('\n')
const result = lines.map(item => {
const newItem = item.split(']')
return {
time: parseTime(newItem[0].slice(1)),
words: newItem[1].trim(),
}
})
return result
}
const lrcData = parseLrc()
console.log(lrcData);
/**
* 将一个时间字符串解析为数字(秒)
* @param {*} timeStr
* @returns
*/
function parseTime(timeStr) {
var part = timeStr.split(':')
// console.log(part);
return +part[0] * 60 + +part[1]
}
/**
* 计算出,当前播放器播放的第几秒,lrcData数组中应该高亮的歌词下标
*/
function findIndex() {
const currentTime = doms.audio.currentTime
// console.log('currentTime', currentTime);
for (var index = 0; index < lrcData.length; index++) {
if (currentTime < lrcData[index].time) {
return index - 1
}
}
return lrcData.length - 1
}
// 渲染界面
function createLrcEl() {
for (let index = 0; index < lrcData.length; index++) {
const lis = document.createElement('li')
lis.innerText = lrcData[index].words
doms.lrcEl.appendChild(lis)
}
}
createLrcEl()
// 盒子的高度
const boxHeight = doms.box.clientHeight
// 每个li的高度
const liHeight = doms.lrcEl.children[0].clientHeight
// 最大的高度
const maxHeight = doms.lrcEl.clientHeight - liHeight
function setOffset() {
// 定位当前高亮歌词下标
const lrcIndex = findIndex()
// 计算需要移动的距离
var moveHeight = liHeight * lrcIndex - (liHeight / 2) - (boxHeight / 2)
if (moveHeight < 0) {
moveHeight = 0
}
if (moveHeight > maxHeight) {
moveHeight = maxHeight
}
doms.lrcEl.style.transform = `translateY(-${moveHeight}px)`
// 添加高亮的样式
const oldLi = doms.lrcEl.querySelector('.active')
if(oldLi){
oldLi.classList.remove('active')
}
const li = doms.lrcEl.children[lrcIndex]
if (li) {
li.classList.add('active')
}
}
doms.audio.addEventListener('timeupdate', setOffset)
拓展:使用到的audio的事件:
audio.addEventListener("timeupdate", callback);
// 播放时间改变时触发