From 6e2a55fe342e982521fc7e0a34e37414c4664396 Mon Sep 17 00:00:00 2001 From: hoelee Date: Tue, 20 Oct 2026 21:00:29 +0800 Subject: [PATCH] fix(lyrics): stop the LRC box pre-highlighting the last line at t=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit findIndex(t > now) - 1 returned -1 before the first line started, which the `if (i < 0) i = lines.length - 1` guard turned into the LAST line — so playback began scrolled to the bottom. Use a last-passed-index scan instead (-1 = before the first line), centre the active line inside the box (so upcoming lyrics are visible), and scroll the box itself rather than scrollIntoView(), which dragged the whole page. Also bumps the box to 250px. Fixes yue2 post + both Suno posts. --- .../how-i-made-my-own-songs-with-suno-ai.md | 17 +++++++++++++---- ...-a-12gb-gpu-songs-that-lost-their-endings.md | 17 +++++++++++++---- .../zh/how-i-made-my-own-songs-with-suno-ai.md | 17 +++++++++++++---- ...-a-12gb-gpu-songs-that-lost-their-endings.md | 17 +++++++++++++---- 4 files changed, 52 insertions(+), 16 deletions(-) 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 + } } }); });