项目目录:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>歌词滚动</title>
<style>
* {
margin: 0;
padding: 0;
user-select: none;
}
html {
height: 100%;
}
body {
color: #009ad6;
text-align: center;
height: 100%;
background-image: url(./assets/dengziqi.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: -400px;
overflow: hidden;
}
.lrc-container {
height: calc(100vh - 360px);
overflow: hidden;
margin-top: 180px;
}
ul,
li {
padding: 0;
margin: 0;
list-style: none;
transition: 0.6s;
}
.play-ico {
display: block;
width: 36px;
height: 36px;
background-image: url(./assets/mcbg.png);
background-repeat: no-repeat;
background-size: 100%;
position: fixed;
right: 50px;
top: 50px;
}
audio {
width: 100%;
height: 100%;
opacity: 0;
display: none;
}
.lrc-container ul>li {
height: 36px;
line-height: 36px;
font-size: 18px;
font-family: '楷体' !important;
transition: 0.6s;
}
.lrc-container ul>li.active {
color: #fff;
transform: scale(1.2);
}
@-webkit-keyframes rotataZ {
0% {
-webkit-transform: rotateZ(0deg);
}
100% {
-webkit-transform: rotateZ(360deg);
}
}
.stop {
background-position: left bottom;
}
.on {
background-position: 0px 1px;
animation: rotataZ 1.2s linear infinite;
}
</style>
</head>
<body>
<span class="play-ico">
<audio src="./assets/taohuanuo.mp3" controls></audio>
</span>
<!-- <button id="clickBtn">点击</button> -->
<div class="lrc-container">
<ul></ul>
</div>
<script src="./js/data.js"></script>
<script src="./js/lrc.js"></script>
</body>
</html>
js
/**
* @desc 歌词滚动的整体实现
*/
(function () {
'use strict';
/**
* @desc 处理歌词数据,字符串转化成对象
* @param { String } lrc
* @returns {Array<object>} 返回值为[object,object,object]
*/
// 解析歌词
function parseLrcs(lrc) {
// 创建一个空数组,用于存储解析后的歌词
const result = [];
// 将歌词按行分割
const lines = lrc.split('\n');
// 遍历每一行歌词
for (let i = 0; i < lines.length; i++) {
// 获取当前行歌词
const line = lines[i];
// 将当前行歌词按']'分割
const parseLrc = line.split(']');
// 创建一个空对象,用于存储当前行歌词的时间和文字
const lrcObj = {};
// 解析当前行歌词的时间
lrcObj.time = parseTime(parseLrc[0].substring(1));
// 解析当前行歌词的文字
lrcObj.words = parseLrc[1];
// 将当前行歌词的对象添加到结果数组中
result.push(lrcObj);
}
// 返回解析后的歌词数组
return result;
}
/**
* @desc 创建 li标签 插入到元素中形成列表
*/
// 创建元素函数
function createElement() {
// 创建文档片段
let frag = document.createDocumentFragment();
// 遍历解析歌词数据
for (let i = 0, len = parseLrcData.length; i < len; i++) {
// 创建li元素
const li = document.createElement('li');
// 将歌词内容设置为li元素的内容
li.textContent = parseLrcData[i].words;
// 将li元素添加到文档片段中
frag.appendChild(li);
}
// 将文档片段添加到ul元素中
doms.ul.appendChild(frag);
}
/**
* @desc 时间字符串转化成数值
* @param { String } 字符串
* @returns { Number } 计算过后的Number
*/
// 将时间字符串转换为分钟
function parseTime(time) {
// 将时间字符串以":"分割成数组
const timeArr = time.split(':');
// 将数组中的小时和分钟转换为数字,并相加
return +timeArr[0] * 60 + +timeArr[1];
}
/**
* @desc 通过对比找到当前时间所在的区间索引
* @param { Number } currTime 当前播放的时间
* @returns { Number } 当前时间对应歌词数据的索引位置
*/
// 遍历歌词数据
function findCurrentIndex(currTime) {
for (let i = 0; i < parseLrcData.length; i++) {
const element = parseLrcData[i];
// 如果当前时间小于歌词时间,则返回当前索引减一
if (currTime < element.time) {
return i - 1;
}
}
// 如果当前时间大于所有歌词时间,则返回歌词数据长度减一
return parseLrcData.length - 1;
}
/**
* @desc 设置偏移量
*/
// 设置偏移量
function setOffset(index) {
// 计算偏移量
let offset = index * liHeight + liHeight / 2 - containerHeight / 2;
// 计算最大偏移量
let maxOffset = doms.ul.clientHeight - containerHeight;
// 如果偏移量小于0,则设置偏移量为0
if (offset < 0) {
offset = 0;
}
// 如果偏移量大于等于最大偏移量,则设置偏移量为最大偏移量
if (offset >= maxOffset) {
offset = maxOffset;
}
// 设置ul的偏移量
doms.ul.style.transform = `translateY(-${offset}px)`;
// 获取当前选中的li
let li = doms.ul.querySelector('.active');
// 如果存在,则移除active类
if (li) {
li.classList.remove('active');
}
// 获取新的li
li = doms.ul.children[index];
// 如果存在,则添加active类
if (li) {
li.classList.add('active');
}
}
// get need operate domain
// 获取页面中的元素
const doms = {
// 歌词容器
lrcContainer: document.querySelector('.lrc-container'),
// 歌词列表
ul: document.querySelector('.lrc-container ul'),
// 音频元素
audio: document.querySelector('audio'),
// 播放按钮
clickBtn: document.querySelector('.play-ico'),
};
const parseLrcData = parseLrcs(lrc1); // 处理过后的歌词数据
createElement(); //create element appended to parent node
// 获取歌词列表项的高度
const liHeight = doms.ul.children[0].clientHeight;
// 获取歌词容器的高度
const containerHeight = doms.lrcContainer.clientHeight;
// 监听音频播放时间更新事件
doms.audio.addEventListener('timeupdate', function (event) {
// 获取当前播放时间
const currentTime = event.target.currentTime;
// 查找当前播放歌词的索引
const currIndex = findCurrentIndex(currentTime);
// 设置歌词偏移量
setOffset(currIndex);
});
// 为点击按钮添加点击事件监听器
doms.clickBtn.addEventListener('click', function () {
// 获取音频是否暂停
let paused = doms.audio.paused;
// 如果暂停
if (paused) {
// 播放音频
doms.audio.play();
// 移除停止按钮样式
doms.clickBtn.classList.remove('stop');
// 添加播放按钮样式
doms.clickBtn.classList.add('on');
} else {
// 暂停音频
doms.audio.pause();
// 添加停止按钮样式
doms.clickBtn.classList.add('stop');
// 移除播放按钮样式
doms.clickBtn.classList.remove('on');
}
});
})();
数据js文件
var lrc = `[00:01.06]难念的经
[00:03.95]演唱:周华健
[00:06.78]
[00:30.96]笑你我枉花光心计
[00:34.15]爱竞逐镜花那美丽
[00:36.75]怕幸运会转眼远逝
[00:39.32]为贪嗔喜恶怒着迷
[00:41.99]责你我太贪功恋势
[00:44.48]怪大地众生太美丽
[00:47.00]悔旧日太执信约誓
[00:49.66]为悲欢哀怨妒着迷
[00:52.56]啊 舍不得璀灿俗世
[00:57.66]啊 躲不开痴恋的欣慰
[01:02.86]啊 找不到色相代替
[01:08.09]啊 参一生参不透这条难题
[01:13.15]吞风吻雨葬落日未曾彷徨
[01:15.73]欺山赶海践雪径也未绝望
[01:18.23]拈花把酒偏折煞世人情狂
[01:20.90]凭这两眼与百臂或千手不能防
[01:23.76]天阔阔雪漫漫共谁同航
[01:26.09]这沙滚滚水皱皱笑着浪荡
[01:28.68]贪欢一刻偏教那女儿情长埋葬
[01:32.38]
[01:34.09]吞风吻雨葬落日未曾彷徨
[01:36.50]欺山赶海践雪径也未绝望
[01:39.07]拈花把酒偏折煞世人情狂
[01:41.69]凭这两眼与百臂或千手不能防
[01:44.68]天阔阔雪漫漫共谁同航
[01:46.93]这沙滚滚水皱皱笑着浪荡
[01:49.54]贪欢一刻偏教那女儿情长埋葬
[01:53.41]
[02:15.45]笑你我枉花光心计
[02:18.53]爱竞逐镜花那美丽
[02:21.14]怕幸运会转眼远逝
[02:23.76]为贪嗔喜恶怒着迷
[02:26.43]责你我太贪功恋势
[02:28.98]怪大地众生太美丽
[02:31.60]悔旧日太执信约誓
[02:34.26]为悲欢哀怨妒着迷
[02:36.90]啊 舍不得璀灿俗世
[02:42.04]啊 躲不开痴恋的欣慰
[02:47.34]啊 找不到色相代替
[02:52.52]啊 参一生参不透这条难题
[02:57.47]吞风吻雨葬落日未曾彷徨
[03:00.05]欺山赶海践雪径也未绝望
[03:02.64]拈花把酒偏折煞世人情狂
[03:05.27]凭这两眼与百臂或千手不能防
[03:08.22]天阔阔雪漫漫共谁同航
[03:10.49]这沙滚滚水皱皱笑着浪荡
[03:13.06]贪欢一刻偏教那女儿情长埋葬
[03:18.45]吞风吻雨葬落日未曾彷徨
[03:20.90]欺山赶海践雪径也未绝望
[03:23.54]拈花把酒偏折煞世人情狂
[03:26.21]凭这两眼与百臂或千手不能防
[03:29.07]天阔阔雪漫漫共谁同航
[03:31.32]这沙滚滚水皱皱笑着浪荡
[03:33.92]贪欢一刻偏教那女儿情长埋葬
[03:39.32]吞风吻雨葬落日未曾彷徨
[03:41.84]欺山赶海践雪径也未绝望
[03:44.38]拈花把酒偏折煞世人情狂
[03:47.04]凭这两眼与百臂或千手不能防
[03:49.99]天阔阔雪漫漫共谁同航
[03:52.20]这沙滚滚水皱皱笑着浪荡
[03:54.89]贪欢一刻偏教那女儿情长埋葬
[04:00.28]吞风吻雨葬落日未曾彷徨
[04:02.68]欺山赶海践雪径也未绝望
[04:05.25]拈花把酒偏折煞世人情狂
[04:07.90]凭这两眼与百臂或千手不能防
[04:10.85]天阔阔雪漫漫共谁同航
[04:13.08]这沙滚滚水皱皱笑着浪荡
[04:15.75]贪欢一刻偏教那女儿情长埋葬
[04:19.48]`;
var lrc1 = `[00:00.000] 作词 : 张赢
[00:00.500] 作曲 : 罗锟
[00:01.000] 编曲 : 罗锟/陈雪燃
[00:01.500] 制作人 : 张赢/陈雪燃
[00:02.00]制作人(美国):Xueran Chen
[00:02.36]制作人(中国):张赢
[00:02.72]人声录音师:姚海毅
[00:03.05]和音:赵贝尔
[00:03.27]管弦乐团:Hungarian symphonic orchestras
[00:03.56]吉他:Jacob Boyd
[00:03.74]中国笛:Chris Bleth
[00:03.96]大提琴:Ro Rowan
[00:04.17]缩混工程师:NEM Studios
[00:04.46]母带工程师:Randy Merrill
[00:04.75]监制:宋鹏飞
[00:04.97]音乐出品发行公司:听见时代传媒
[00:05.80]
[00:19.71]初见若缱绻 誓言 风吹云舒卷
[00:26.17]
[00:26.98]岁月间 问今夕又何年
[00:32.00]
[00:33.44]心有犀但愿 执念 轮回过经年
[00:39.93]
[00:40.81]弹指间 繁花开落多少遍
[00:45.39]
[00:47.17]这一世牵绊 纠结 触动了心弦
[00:53.49]
[00:54.43]下一世 不知可否再见
[00:59.52]
[01:00.95]留一片桃花 纪念 了却浮生缘
[01:07.47]
[01:08.22]眉目间 还有我的思念
[01:13.01]
[01:15.02]一寸土 一年木 一花一树一贪图
[01:20.86]
[01:21.81]情是种 爱偏开在迷途
[01:27.16]
[01:28.68]忘前路 忘旧物 忘心忘你忘最初
[01:34.79]
[01:35.44]花斑斑 留在爱你的路
[01:41.15]
[01:55.85]这一世牵绊 纠结 触动了心弦
[02:02.19]
[02:02.91]下一世 不知可否再见
[02:08.08]
[02:09.37]留一片桃花 纪念 了却浮生缘
[02:16.02]
[02:16.60]眉目间 还有我的思念
[02:21.71]
[02:23.57]一寸土 一年木 一花一树一贪图
[02:29.52]
[02:30.32]情是种 爱偏开在迷途
[02:35.58]
[02:37.17]忘前路 忘旧物 忘心忘你忘最初
[02:43.30]
[02:43.94]花斑斑 留在爱你的路
[02:48.92]
[02:50.53]虔诚夙愿 来世路
[02:53.59]
[02:54.30]一念桃花因果渡
[02:56.99]
[02:57.65]那一念 几阙时光在重复
[03:03.46]
[03:04.67]听雨书 望天湖 人间寥寥情难诉
[03:11.37]回忆斑斑 留在爱你的路`;
mp3文件
tips:如果需要自行下载
图片文件
tips:如果需要去自行下载
本站代码模板仅供学习交流使用请勿商业运营,严禁从事违法,侵权等任何非法活动,否则后果自负!
WX234.CN
暂无评论内容