原生lrc歌词同步(测试二)
本帖最后由 马黑黑 于 2023-2-18 20:40 编辑 <br /><br /><style>#papa {
margin: auto;
padding: 20px;
width: 700px;
height: 400px;
box-shadow: 3px 3px 20px #000;
position: relative;
}
#lrc {
--motion: cover2;
--tt: 2s;
--state: paused;
--bg: linear-gradient(180deg, hsla(60, 50%, 50%, .45), hsla(80, 70%, 50%, .65));
position: absolute;
font: bold 2em sans-serif;
color: snow;
white-space: pre;
-webkit-background-clip: text;
filter: drop-shadow(1px 1px 2px hsla(0, 0%, 0%, .95));
}
#lrc::before {
position: absolute;
content: attr(data-lrc);
width: 20%;
height: 100%;
color: transparent;
overflow: hidden;
white-space: pre;
background: var(--bg);
filter: inherit;
-webkit-background-clip: text;
animation: var(--motion) var(--tt) linear forwards;
animation-play-state: var(--state);
}
@keyframes cover1 { from { width: 0; } to { width: 100%; } }
@keyframes cover2 { from { width: 0; } to { width: 100%; } }
@keyframes rot { to { transform: rotate(1turn); } }
</style>
<div id="papa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2015286363.mp3" controls loop autoplay></audio>
<div id="lrc" data-lrc="HCPlayer">HCPlayer</div>
</div>
<script>
/*原始lrc歌词*/
let lrcStr = `
韩红 - 望
长风落进斜阳
悲歌多断肠
一卷天下涛与浪
惊魂破绝然踏蹄扬
燃尽卑微的我
无声轻轻坠落
怀一腔血赤胆忠良
撑一撑就到天亮
迢迢归乡之路
孤单伴着满足
曾几时梦里
遇见过你
就此别过亦是幸福
遥遥壮烈时刻
幸得慷慨一搏
不畏浮云遮望眼
何惧世间起浓烟
唱一生忠义
颂英雄之躯
蓦然间回首
收紧了心头
听那首人间悲曲
一曲悲歌
一世离合
皆化作山河
一曲悲歌
一世离合
仰天长啸一首歌
感谢欣赏
`;
/*变量 :mKey - 当前歌词索引;mFlag :调用关键帧动画索引*/
let mKey = 0, mFlag = true;
/*函数 :获取每句歌词用时,歌词用时若超过平均值则取平均值,最后一句歌词则取平均值*/
let lrcTime = (ar) => {
let tmpAr = [];
for(j = 0; j <ar.length - 1; j ++) {
if(j !== ar.length - 1) tmpAr = parseFloat((ar - ar).toFixed(1));
}
let aver = parseInt(tmpAr.reduce((a,b) => a + b) / (tmpAr.length - 1));
tmpAr.push(aver);
tmpAr.forEach((item,key) => {
ar = item > aver ? aver : item;
});
return ar;
};
/*函数 :从原始lrc歌词获取信息并存入 n*2 数组*/
let getLrcAr = (str) => {
str = str.trim();
let lines = [], lrcAr = [];
let reg = /\[(\d{1,}:\d{1,}.\d{1,})\](.*)/g;
if(!str.match(reg)) return;
lines = str.replace(reg,'$1-{}-$2').split('\n');
for(k = 0; k < lines.length; k ++) {
lrcAr = [];
for(j = 0; j < 3; j ++) {
let tmpAr = lines.split('-{}-');
lrcAr = j === 0 ? toSecs(tmpAr) : tmpAr;
}
}
return lrcTime(lrcAr); /* 数组变为 n*3 */
};
/*函数 :原始lrc时间转为秒数*/
let toSecs = (lrcTime) => {
let reg = /\d{2,}/g;
let ar = lrcTime.match(reg);
return ar*60 + parseInt(ar) + parseInt((ar)/1000);
};
/*函数 :模拟显示同步歌词*/
let showLrc = (time) => {
let name = mFlag ? 'cover1' : 'cover2';
lrc.innerHTML = lrcAr;
lrc.dataset.lrc = lrcAr;
lrc.style.setProperty('--motion', name);
lrc.style.setProperty('--tt', time + 's');
lrc.style.setProperty('--state', 'running');
mKey += 1;
mFlag = !mFlag;
};
/*函数 :处理当前歌词索引 mKey*/
let calcKey = () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime <= lrcAr) {
mKey = j - 1;
break;
}
}
if (mKey < 0) mKey = 0;
if (mKey > lrcAr.length - 1) mKey = lrcAr.length - 1;
let time = lrcAr - (aud.currentTime - lrcAr);
showLrc(time);
};
/*格式化时间信息*/
let toMin = (val) => {
if (!val) return '00:00';
val = Math.floor(val);
let min = parseInt(val / 60),
sec = parseFloat(val % 60);
if (min < 10) min = '0' + min;
if (sec < 10) sec = '0' + sec;
return min + ':' + sec;
}
/*函数 :歌词同步状态切换*/
let mState = () => lrc.style.setProperty('--state', aud.paused ? 'paused' : 'running');
/*监听播放进度*/
aud.addEventListener('timeupdate', () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime >= lrcAr) {
cKey = j;
if (mKey === j) showLrc(lrcAr);
else continue;
}
}
});
aud.addEventListener('pause', () => mState());/*监听暂停事件*/
aud.addEventListener('play', () => mState());/*监听播放事件*/
aud.addEventListener('seeked', () => calcKey());/*监听查询事件*/
let lrcAr = getLrcAr(lrcStr); /*获得歌词数组*/
</script> 代码
<style>
#papa {
margin: auto;
padding: 20px;
width: 700px;
height: 400px;
box-shadow: 3px 3px 20px #000;
position: relative;
}
#lrc {
--motion: cover2;
--tt: 2s;
--state: paused;
--bg: linear-gradient(180deg, hsla(60, 50%, 50%, .45), hsla(80, 70%, 50%, .65));
position: absolute;
font: bold 2em sans-serif;
color: snow;
white-space: pre;
-webkit-background-clip: text;
filter: drop-shadow(1px 1px 2px hsla(0, 0%, 0%, .95));
}
#lrc::before {
position: absolute;
content: attr(data-lrc);
width: 20%;
height: 100%;
color: transparent;
overflow: hidden;
white-space: pre;
background: var(--bg);
filter: inherit;
-webkit-background-clip: text;
animation: var(--motion) var(--tt) linear forwards;
animation-play-state: var(--state);
}
@keyframes cover1 { from { width: 0; } to { width: 100%; } }
@keyframes cover2 { from { width: 0; } to { width: 100%; } }
@keyframes rot { to { transform: rotate(1turn); } }
</style>
<div id="papa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2015286363.mp3" controls loop autoplay></audio>
<div id="lrc" data-lrc="HCPlayer">HCPlayer</div>
</div>
<script>
/*原始lrc歌词*/
let lrcStr = `
韩红 - 望
长风落进斜阳
悲歌多断肠
一卷天下涛与浪
惊魂破绝然踏蹄扬
燃尽卑微的我
无声轻轻坠落
怀一腔血赤胆忠良
撑一撑就到天亮
迢迢归乡之路
孤单伴着满足
曾几时梦里
遇见过你
就此别过亦是幸福
遥遥壮烈时刻
幸得慷慨一搏
不畏浮云遮望眼
何惧世间起浓烟
唱一生忠义
颂英雄之躯
蓦然间回首
收紧了心头
听那首人间悲曲
一曲悲歌
一世离合
皆化作山河
一曲悲歌
一世离合
仰天长啸一首歌
感谢欣赏
`;
/*变量 :mKey - 当前歌词索引;mFlag :调用关键帧动画索引*/
let mKey = 0, mFlag = true;
/*函数 :获取每句歌词用时,歌词用时若超过平均值则取平均值,最后一句歌词则取平均值*/
let lrcTime = (ar) => {
let tmpAr = [];
for(j = 0; j <ar.length - 1; j ++) {
if(j !== ar.length - 1) tmpAr = parseFloat((ar - ar).toFixed(1));
}
let aver = parseInt(tmpAr.reduce((a,b) => a + b) / (tmpAr.length - 1));
tmpAr.push(aver);
tmpAr.forEach((item,key) => {
ar = item > aver ? aver : item;
});
return ar;
};
/*函数 :从原始lrc歌词获取信息并存入 n*2 数组*/
let getLrcAr = (str) => {
str = str.trim();
let lines = [], lrcAr = [];
let reg = /\[(\d{1,}:\d{1,}.\d{1,})\](.*)/g;
if(!str.match(reg)) return;
lines = str.replace(reg,'$1-{}-$2').split('\n');
for(k = 0; k < lines.length; k ++) {
lrcAr = [];
for(j = 0; j < 3; j ++) {
let tmpAr = lines.split('-{}-');
lrcAr = j === 0 ? toSecs(tmpAr) : tmpAr;
}
}
return lrcTime(lrcAr); /* 数组变为 n*3 */
};
/*函数 :原始lrc时间转为秒数*/
let toSecs = (lrcTime) => {
let reg = /\d{2,}/g;
let ar = lrcTime.match(reg);
return ar*60 + parseInt(ar) + parseInt((ar)/1000);
};
/*函数 :模拟显示同步歌词*/
let showLrc = (time) => {
let name = mFlag ? 'cover1' : 'cover2';
lrc.innerHTML = lrcAr;
lrc.dataset.lrc = lrcAr;
lrc.style.setProperty('--motion', name);
lrc.style.setProperty('--tt', time + 's');
lrc.style.setProperty('--state', 'running');
mKey += 1;
mFlag = !mFlag;
};
/*函数 :处理当前歌词索引 mKey*/
let calcKey = () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime <= lrcAr) {
mKey = j - 1;
break;
}
}
if (mKey < 0) mKey = 0;
if (mKey > lrcAr.length - 1) mKey = lrcAr.length - 1;
let time = lrcAr - (aud.currentTime - lrcAr);
showLrc(time);
};
/*格式化时间信息*/
let toMin = (val) => {
if (!val) return '00:00';
val = Math.floor(val);
let min = parseInt(val / 60),
sec = parseFloat(val % 60);
if (min < 10) min = '0' + min;
if (sec < 10) sec = '0' + sec;
return min + ':' + sec;
}
/*函数 :歌词同步状态切换*/
let mState = () => lrc.style.setProperty('--state', aud.paused ? 'paused' : 'running');
/*监听播放进度*/
aud.addEventListener('timeupdate', () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime >= lrcAr) {
cKey = j;
if (mKey === j) showLrc(lrcAr);
else continue;
}
}
});
aud.addEventListener('pause', () => mState());/*监听暂停事件*/
aud.addEventListener('play', () => mState());/*监听播放事件*/
aud.addEventListener('seeked', () => calcKey());/*监听查询事件*/
let lrcAr = getLrcAr(lrcStr); /*获得歌词数组*/
</script>
此测试与测试一相比:解决分行歌词的问题,即,原始lrc歌词可以是这样定义——
let lrcStr = `
第一句歌词
第二句歌词
第N句歌词
`;
你若喜欢,每句歌词信息可以不顶格 说明一下:网络lrc歌词,正如 @小辣椒 所说的,都不太准确,有条件、有时间还是自己制作的好,这类软件还是很多的。如果不想自己制作,那么,可以自己调整,大约仅调整秒数就好 parseInt((ar)/1000)恒等于 0 歌词信息顶格和不顶格没明白是怎么回事。 黑黑一弄再弄,辛苦了{:4_187:} 红影 发表于 2023-2-18 21:50
黑黑一弄再弄,辛苦了
辛苦谈不上 好方式,有创意! 庶民 发表于 2023-2-19 05:05
好方式,有创意!
{:5_108:} 小辣椒迟到的观众{:4_170:} 本帖最后由 马黑黑 于 2023-2-19 14:12 编辑
起个网名好难 发表于 2023-2-18 21:05
parseInt((ar)/1000)恒等于 0
对,强制整数。开始用的是parseFloat,后来反复修改改错地方了。 小辣椒 发表于 2023-2-19 13:27
小辣椒迟到的观众
测试中,没关系 马黑黑 发表于 2023-2-19 13:56
对,强制整数。开始用的是parseFloat,后来反复修改改错地方了。
反正是秒也就无所谓了 起个网名好难 发表于 2023-2-19 15:50
反正是秒也就无所谓了
嗯,试过效果,区别肉眼几乎看不出 马黑黑 发表于 2023-2-19 18:14
嗯,试过效果,区别肉眼几乎看不出
确实 马黑黑 发表于 2023-2-19 18:14
嗯,试过效果,区别肉眼几乎看不出
请教“获取每句歌词用时,歌词用时若超过平均值则取平均值,最后一句歌词则取平均值” 有什么根据
马黑黑 发表于 2023-2-18 23:10
辛苦谈不上
前面光顾着看代码了,现在听来这首还真好听呢{:4_187:} 红影 发表于 2023-2-19 18:47
前面光顾着看代码了,现在听来这首还真好听呢
猜猜谁唱的
页:
[1]
2