diff --git a/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md b/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md index 01ab374..248fc7c 100644 --- a/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md +++ b/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md @@ -88,7 +88,7 @@ Publitio) and embedded with plain HTML5 audio. Press play: @@ -287,12 +287,21 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { let cur = -1; audio.addEventListener('timeupdate', () => { const now = audio.currentTime; - let i = lines.findIndex((l) => l.t > now) - 1; - if (i < 0) i = lines.length - 1; + // last line whose timestamp has passed; -1 before the first line starts + // (findIndex()-1 went negative at t=0 and wrapped to the LAST line) + let i = -1; + for (let k = 0; k < lines.length; k++) { if (lines[k].t <= now) i = k; else break; } if (i !== cur) { if (cur >= 0) box.children[cur].classList.remove('on'); cur = i; - if (cur >= 0) { box.children[cur].classList.add('on'); box.children[cur].scrollIntoView({ block: 'nearest' }); } + if (cur >= 0) { + const p = box.children[cur]; + p.classList.add('on'); + // scroll the lyric box only (scrollIntoView would drag the whole page) + box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + } else { + box.scrollTop = 0; // back to the top before the first line + } } }); }); diff --git a/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md b/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md index ce87a12..283025f 100644 --- a/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md +++ b/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md @@ -227,7 +227,7 @@ against the written lyrics, since the model emits no timestamps. @@ -951,12 +951,21 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { let cur = -1; audio.addEventListener('timeupdate', () => { const now = audio.currentTime; - let i = lines.findIndex((l) => l.t > now) - 1; - if (i < 0) i = lines.length - 1; + // last line whose timestamp has passed; -1 before the first line starts + // (findIndex()-1 went negative at t=0 and wrapped to the LAST line) + let i = -1; + for (let k = 0; k < lines.length; k++) { if (lines[k].t <= now) i = k; else break; } if (i !== cur) { if (cur >= 0) box.children[cur].classList.remove('on'); cur = i; - if (cur >= 0) { box.children[cur].classList.add('on'); box.children[cur].scrollIntoView({ block: 'nearest' }); } + if (cur >= 0) { + const p = box.children[cur]; + p.classList.add('on'); + // scroll the lyric box only (scrollIntoView would drag the whole page) + box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + } else { + box.scrollTop = 0; // back to the top before the first line + } } }); }); diff --git a/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md b/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md index d1bcbbb..2d8e987 100644 --- a/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md +++ b/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md @@ -74,7 +74,7 @@ v6 家族新增的控制功能,直接改变了我做事的方式: @@ -266,12 +266,21 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { let cur = -1; audio.addEventListener('timeupdate', () => { const now = audio.currentTime; - let i = lines.findIndex((l) => l.t > now) - 1; - if (i < 0) i = lines.length - 1; + // last line whose timestamp has passed; -1 before the first line starts + // (findIndex()-1 went negative at t=0 and wrapped to the LAST line) + let i = -1; + for (let k = 0; k < lines.length; k++) { if (lines[k].t <= now) i = k; else break; } if (i !== cur) { if (cur >= 0) box.children[cur].classList.remove('on'); cur = i; - if (cur >= 0) { box.children[cur].classList.add('on'); box.children[cur].scrollIntoView({ block: 'nearest' }); } + if (cur >= 0) { + const p = box.children[cur]; + p.classList.add('on'); + // scroll the lyric box only (scrollIntoView would drag the whole page) + box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + } else { + box.scrollTop = 0; // back to the top before the first line + } } }); }); diff --git a/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md b/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md index 7930a20..8367626 100644 --- a/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md +++ b/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md @@ -172,7 +172,7 @@ clean = "\n".join(l for l in raw.split("\n") @@ -896,12 +896,21 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { let cur = -1; audio.addEventListener('timeupdate', () => { const now = audio.currentTime; - let i = lines.findIndex((l) => l.t > now) - 1; - if (i < 0) i = lines.length - 1; + // last line whose timestamp has passed; -1 before the first line starts + // (findIndex()-1 went negative at t=0 and wrapped to the LAST line) + let i = -1; + for (let k = 0; k < lines.length; k++) { if (lines[k].t <= now) i = k; else break; } if (i !== cur) { if (cur >= 0) box.children[cur].classList.remove('on'); cur = i; - if (cur >= 0) { box.children[cur].classList.add('on'); box.children[cur].scrollIntoView({ block: 'nearest' }); } + if (cur >= 0) { + const p = box.children[cur]; + p.classList.add('on'); + // scroll the lyric box only (scrollIntoView would drag the whole page) + box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + } else { + box.scrollTop = 0; // back to the top before the first line + } } }); });