{"id":217,"date":"2023-10-29T02:34:30","date_gmt":"2023-10-28T18:34:30","guid":{"rendered":"http:\/\/39.105.184.3\/?p=217"},"modified":"2026-04-29T21:23:34","modified_gmt":"2026-04-29T13:23:34","slug":"%e6%9c%80%e9%95%bf%e7%9a%84%e7%94%b5%e5%bd%b1","status":"publish","type":"post","link":"https:\/\/fanyiming.life\/?p=217","title":{"rendered":"\u6700\u957f\u7684\u7535\u5f71"},"content":{"rendered":"\n<audio id=\"audio-player\" controls>\n    <source src=\"https:\/\/fanym.oss-cn-beijing.aliyuncs.com\/wp-content\/uploads\/2024\/09\/zuichangdedianying.mp3\" type=\"audio\/mp3\">\n    \u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u97f3\u9891\u64ad\u653e\u3002\n<\/audio>\n\n<div id=\"lyrics-container\" style=\"overflow-y: auto; max-height: 350px; border: 1px solid #ccc; padding: 10px; margin-top: 10px; position: relative;\">\n    <ul id=\"lyrics\"><\/ul>\n<\/div>\n\n<script>\ndocument.addEventListener('DOMContentLoaded', async function () {\n    const audio = document.getElementById('audio-player');\n    const lyricsContainer = document.getElementById('lyrics');\n    const container = document.getElementById('lyrics-container');\n    const lyricsFile = 'https:\/\/fanym.oss-cn-beijing.aliyuncs.com\/wp-content\/uploads\/2024\/09\/zuichangdedianying.lrc';\n    let currentIndex = 0;\n    let lyrics = [];\n    let isUserScrolling = false;\n    let scrollTimeout;\n\n    const lrcText = await fetchLyrics(lyricsFile);\n    parseLRC(lrcText);\n\n    function fetchLyrics(url) {\n        return fetch(url).then(response => response.text());\n    }\n\n    function parseLRC(lrcText) {\n        const lines = lrcText.split('\\n');\n        lyrics = lines.map(line => {\n            const timeMatch = line.match(\/\\[(\\d{2}):(\\d{2})\\.(\\d{1,2})\\]\/);\n            if (timeMatch) {\n                const minutes = parseInt(timeMatch[1], 10);\n                const seconds = parseInt(timeMatch[2], 10);\n                const milliseconds = parseInt(timeMatch[3].padEnd(2, '0'), 10);\n                const timeInSeconds = minutes * 60 + seconds + milliseconds \/ 100;\n                const lyricText = line.replace(\/\\[.*?\\]\/g, '').trim();\n                return { time: timeInSeconds, text: lyricText };\n            }\n            return { time: null, text: line.trim() };\n        });\n        renderLyrics();\n    }\n\n    function renderLyrics() {\n        const fragment = document.createDocumentFragment();\n        lyrics.forEach((lyric) => {\n            const li = document.createElement('li');\n            li.textContent = lyric.text;\n            if (lyric.time !== null) {\n                li.dataset.time = lyric.time.toString();\n                li.addEventListener('click', (event) => {\n                    const clickedLi = event.target;\n                    const clickedTime = parseFloat(clickedLi.dataset.time);\n                    audio.currentTime = clickedTime;\n                    const clickedIndex = Array.from(document.querySelectorAll('#lyrics li')).indexOf(clickedLi);\n                    highlightLyric(clickedLi);\n                    scrollToLyric(clickedIndex);\n                });\n            }\n            fragment.appendChild(li);\n        });\n        lyricsContainer.innerHTML = '';\n        lyricsContainer.appendChild(fragment);\n    }\n\n    function synchronizeLyricsWithAudio(currentTime) {\n        const lines = document.querySelectorAll('#lyrics li');\n        let foundIndex = -1;\n\n        lyrics.forEach((lyric, index) => {\n            if (lyric.time && lyric.time <= currentTime + 0.5) {\n                foundIndex = index;\n            }\n        });\n\n        if (foundIndex >= 0 && !isUserScrolling) {\n            currentIndex = foundIndex;\n            highlightLyric(lines[currentIndex]);\n            scrollToLyric(currentIndex);\n        }\n    }\n\n    audio.addEventListener('timeupdate', function () {\n        const currentTime = audio.currentTime;\n        synchronizeLyricsWithAudio(currentTime);\n    });\n\n    function highlightLyric(line) {\n        document.querySelectorAll('#lyrics li').forEach(li => li.classList.remove('highlight'));\n        line.classList.add('highlight');\n    }\n\n    function scrollToLyric(index) {\n        const line = document.querySelectorAll('#lyrics li')[index];\n        const offsetTop = line.offsetTop;\n        const containerHeight = container.offsetHeight;\n        const lineHeight = line.offsetHeight;\n        const scrollTop = container.scrollTop;\n        const scrollBottom = scrollTop + containerHeight;\n\n        if (offsetTop < scrollTop || offsetTop + lineHeight > scrollBottom) {\n            if (container.scrollHeight > container.offsetHeight) {\n                const scrollTarget = Math.max(0, offsetTop - containerHeight \/ 5 + lineHeight \/ 5);\n                container.scrollTop = scrollTarget;\n            }\n        }\n    }\n\n    container.addEventListener('scroll', function () {\n        isUserScrolling = true;\n        clearTimeout(scrollTimeout);\n        scrollTimeout = setTimeout(() => {\n            isUserScrolling = false;\n        }, 3000);\n    });\n});\n<\/script>\n\n<style>\n    #lyrics li {\n        list-style: none;\n        padding: 5px;\n        color: #333;\n        cursor: pointer;\n    }\n\n    #lyrics li.highlight {\n        color: #d9534f;\n        font-weight: bold;\n        font-size: 1.2em;\n        background-color: rgba(255, 215, 0, 0.2);\n    }\n\n    #audio-player {\n        width: 100%;\n    }\n\n    #lyrics-container {\n        scroll-behavior: smooth;\n    }\n<\/style>\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u7bc7\u5173\u4e8e\u5468\u6770\u4f26\u300a\u6700\u957f\u7684\u7535\u5f71\u300b\u6b4c\u8bcd\u7684\u6536\u85cf\u6574\u7406\uff0c\u914d\u4e0a\u4e86\u53ef\u540c\u6b65\u64ad\u653e\u7684\u97f3\u9891\u4e0e\u9010\u884c\u9ad8\u4eae\u7684LRC\u6b4c\u8bcd\u3002\u4e0d\u4ec5\u662f\u4e00\u6bb5\u65cb\u5f8b\u7684\u5b58\u6863\uff0c\u66f4\u662f\u4e00\u4efd\u6309\u65f6\u95f4\u8f74\u6807\u8bb0\u7684\u60c5\u611f\u7d22\u5f15\u2014\u2014\u5f53\u7ea2\u8272\u9ad8\u4eae\u968f\u97f3\u4e50\u6eda\u52a8\uff0c\u90a3\u4e9b\u88ab\u5b9a\u683c\u5728\u6b4c\u8bcd\u91cc\u7684\u753b\u9762\u4e0e\u60c5\u7eea\uff0c\u6216\u8bb8\u6bd4\u4f60\u8bb0\u5fc6\u4e2d\u7684\u66f4\u6e05\u6670\u4e00\u70b9\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-217","post","type-post","status-publish","format-standard","hentry","category-12"],"_links":{"self":[{"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/posts\/217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fanyiming.life\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=217"}],"version-history":[{"count":13,"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/posts\/217\/revisions"}],"predecessor-version":[{"id":14814,"href":"https:\/\/fanyiming.life\/index.php?rest_route=\/wp\/v2\/posts\/217\/revisions\/14814"}],"wp:attachment":[{"href":"https:\/\/fanyiming.life\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fanyiming.life\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fanyiming.life\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}