|
|
<style>
#pa {
margin: 20px auto;
width: 1024px ;
height: 640px;
border: 1px solid gray;
display: grid;
place-items: center;
position: relative;
}
#wrapper {
position: absolute;
padding: 10px;
font: bold 2rem/1.2 sans-serif;
text-shadow: 1px 1px 1px gray;
bottom: 20px;
}
.char {
display: inline-block;
padding: 0 2px;
opacity: 0;
transform: translate(var(--x), var(--y));
animation: fadeIn 0.3s var(--delay) forwards;
}
audio { position: absolute; left: 20px; top: 20px; }
@keyframes fadeIn {
to {
transform: translate(0, 0);
opacity: 1;
}
}
</style>
<div id="pa">
<audio id="aud" src="https://cccimg.com/view.php/7404fa9c5e73097aefa645b90d63a7a2.mp3" controls autoplay></audio>
<div id="wrapper">HUACHAO LRC</div>
</div>
<script>
const gc = `、[00:00.0]终于把你遇见 - 徐子崴/罗姣\n
[00:03.18]词:徐子崴\n
[00:04.4]曲:徐子崴\n
[00:05.62]编曲:冯丹\n
[00:06.84]吉他:孙越\n
[00:08.07]萧:丁晓逵\n
[00:09.29]伴唱:凌菲\n
[00:10.51]录音:欧力\n
[00:11.74]录音棚:崴IP•MUSIC\n
[00:13.45]音频编辑 Audio Editor:刘璇\n
[00:15.65]混音工程师 Mixing Engineer:王路遥\n
[00:18.34]母带工程师 Mastering Engineer:王路遥\n
[00:21.03]录音/混音/母带棚:@2496 Top Music\n
[00:24.21]封面设计:李政\n
[00:25.92]出品:福唱音乐\n
[00:27.64]制作人:徐子崴\n
[00:29.35]如果一生有一百年\n
[00:35.75]不过是三万六千五百天\n
[00:42.19]我穿过河流啊我越过高山\n
[00:48.66]只为能和你见呀见\n一面\n
[00:55.18]如果一生有一百年\n
[01:01.7]说起来很长说来也很短\n
[01:08.24]我仰望日月啊我祈求上天\n
[01:14.64]只为能和你走呀走一段\n
[01:27.729996]多想把你遇\n见
[01:34.1]恰好在对的时间\n
[01:40.68]我愿用前世的苦难\n
[01:47.11]换与你今生的情缘\n
[01:53.44]终于把你遇见\n
[02:00.05]恰好在对的时间\n
[02:06.58]我愿以今生的相伴\n
[02:13.08]许和你来世的圆满\n
[02:45.52]如果一生有一百年\n
[02:51.95999]说起来很长说来也很短\n
[02:58.49]我仰望日月啊我祈求上天\n
[03:04.94]只为能和你走呀走一段\n
[03:14.75]多想把你遇见\n
[03:21.19]恰好在对的时间\n
[03:27.70999]我愿用前世的苦难\n
[03:34.16]换与你今生的情缘\n
[03:40.61]终于把你遇见\n
[03:47.07]恰好在对的时间\n
[03:53.67]我愿以今生的相伴\n
[04:00.08]许和你来世的圆满\n
[04:06.56]许和你来世的圆满`;
const gcAr = lrc2HC(gc);
let curkey = 0, isSeeking = false;
aud.ontimeupdate = () => {
if(curkey > gcAr.length - 1) return;
if(aud.currentTime >= gcAr[curkey][0]) {
const gap = gcAr[curkey + 1]?.[0] ?? 0 - gcAr[curkey][0];
showLrc(gcAr[curkey][1], wrapper, gap);
}
};
aud.onended = () => {
curkey = 0;
aud.play();
}
aud.onseeked = () => calcKey();
function lrc2HC(text) {
let lrcAr = [];
let ar = text.trim().split('\n');
ar.sort();
let reg = /\[(\d+)[.:](\d+)[.:](\d+)\](.*)/;
ar.forEach(item => {
if(reg.test(item)) {
let result = item.match(reg);
let tmsg = parseInt(result[1]) * 60 + parseInt(result[2]) + parseInt(result[3]) / 1000;
lrcAr.push([tmsg, result[4].trim()]);
}
});
return lrcAr ? lrcAr : [0, 'HUACHAO'];
};
function calcKey() {
for (let j = 0; j < gcAr.length; j++) {
if (aud.currentTime <= gcAr[j][0]) {
curkey = j - 1;
break;
}
}
if (curkey < 0) curkey = 0;
if (curkey > gcAr.length - 1) curkey = gcAr.length - 1;
let time = gcAr[curkey + 1]?.[0] ?? 0 - gcAr[curkey][0];
isSeeking = false;
showLrc(gcAr[curkey][1], wrapper, time);
}
function showLrc(str, targetElm, time) {
if(isSeeking) return;
targetElm.innerHTML = '';
const chars = str.split('').map(c => c === ' ' ? ' ' : c);
const frg = document.createDocumentFragment();
chars.forEach((char, idx) => {
const span = document.createElement('span');
span.innerHTML = char;
span.classList.add('char');
const x = Math.random() * (Math.random() > 0.5 ? 300 : -300);
const y = Math.random() * (Math.random() > 0.5 ? 300 : -300);
span.style.cssText += `
color: #${Math.random().toString(16).substring(2,8)};
--x: ${x}px;
--y: ${y}px;
--delay: ${Math.random() * 0.5}s;
`;
frg.appendChild(span);
});
targetElm.appendChild(frg);
curkey ++;
setTimeout(() =>isSeeking = false, time);
}
</script>
|
|