亚伦影音工作室 发表于 2025-8-18 20:59

猫头播放器【时光匆匆如流水-影子】

本帖最后由 亚伦影音工作室 于 2025-8-24 09:09 编辑 <br /><br /><style>
#gc{margin: 120px -25%;position: relative;z-index: 1;width: 750px;}
.lyrics{margin: 0;
            top: 0px;
            left: 50%;
    transform: translate(-50%, -50%);
            height: 100px; /* 调整高度,只容纳当前歌词 */
                 text-align: center;
            position: absolute;z-index: 50;
      }
            .lyric-line{
            width: 100%;
            position: relative;
            height: 60px;
            overflow: visible;
   font: 300 50px '华文隶书', sans-serif;
            line-height: 60px;
         text-align: left;
            
            white-space: nowrap; /* 禁止换行 */
            filter: drop-shadow(#fff 1px 0 0) drop-shadow(#fff 0 1px 0) drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px 0);
      }

      .lyric-mask {
            position: absolute;
            top: 0;
            left: 0;
            width: 0;
            overflow: hidden;
      color: #8B4513;
            height: 100%;
            white-space: nowrap;
      }

      .lyric-original {
             color: #ag0000;
            white-space: nowrap;
            
      }   

</style>
<style>
@keyframes an-pupils {
    from {transform: rotate(0deg);
      left: 30px;
    }
    to {transform: rotate(360deg);
      left: 0px;
    }
}

@keyframes an-ears {
    from {
       top:0;
    }
    to {
       top:25px;
    }
}



#cat {position: relative;
        width: 480px;z-index: 20;
        margin:20px auto;
}


#head {
        width: 400px;
        height: 370px;
        background-color: #171717;
        border-radius: 50%;
        margin: auto;
}

#ears {
height: 65px;
position: relative;
left: 35px;
animation-name: an-ears;
    animation-duration: 1s;
    animation-iteration-count: infinite;
    animation-direction: alternate-reverse;
}

.ear{
        width: 0;
        height: 0;
        border-left: 90px solid transparent;
        border-right: 90px solid transparent;
        border-bottom: 160px solid #171717;
        font-size: 0;
        line-height: 0;
        float: left;
        margin-right: 60px;
       
    transform: rotate(35deg);
      
}


.ear:first-child {
       
    transform: rotate(-35deg);
}

#eyes {
        clear: both;
        width: 350px;
        position: relative;
        top: 25px;
        left: 53px;
}

.eye {
        width: 120px;
        height: 120px;
        background-color: #FFFFFF;
        border-radius: 50%;
        float: left;
       
}

.eye:first-child {
        margin-right: 50px;
}

.pupil {
        position: relative;
        top:40px;
        background-color: #171717;
        border-radius: 50%;
        width: 80px;
        height: 80px;
animation-name: an-pupils;
    animation-duration: 1.5s;
    animation-iteration-count: infinite;
    animation-direction: alternate-reverse;
}

.pupil_ref {
        background-color: #FFFFFF;
        border-radius: 45%;
        width: 30px;
        height: 30px;
        position: relative;
        top: 40px;
        left: 10px;

}

#nose {
        width: 45px;
        height: 30px;
        border-radius: 50%;
        background-color: #FFFFFF;
        position: relative;
        top: 160px;
        left: 170px;
}

#baffisx {
position: relative;
left: -105px;
top: 100px; transform-origin: 70% 0%;
animation: hue-rotate 1s linear infinite ;
}
@keyframes hue-rotate {
from {transform: rotate(-15deg);margin: 0px 0px;
}
to {margin: 0px 0px;transform: rotate(15deg);
}
}
#baffidx {
position: relative;
left: 223px;
top: 140px;
transform-origin: 0% 0%;
    animation: hue 1s linear infinite ;
}
@keyframes hue {
from {transform: rotate(15deg);margin: 0px 0px;
    }
to {
margin: 0px 0px;transform: rotate(-15deg);
}
}
.baffo{
width:260px;
height:5px;
border:solid 4px #fff;
border-color:#555 transparent transparent transparent;
border-radius: 60%/30px 30px 0 0;

}
</style>
<div id="cat">
<div id="ears">
<div class="ear"></div>
<div class="ear"></div>
</div>

                <div id="head">
<div id="eyes">
<div class="eye" >
<div class="pupil" id="p1"><div class="pupil_ref"></div></div>
</div>
<div class="eye" >
<div class="pupil" id="p2"><div class="pupil_ref"></div></div>
</div>
               </div>

                        <div id="nose"></div>
                        <div id="baffidx">
                                        <div class="baffo"></div>
                                        <div class="baffo"></div>
                                        <div class="baffo"></div>
                        </div>

                        <div id="baffisx">
                                        <div class="baffo"></div>
                                        <div class="baffo"></div>
                                        <div class="baffo"></div>
                        </div>
                </div>
<div id="gc">
<div class="lyrics">
            <div class="lyric-line">
                  <div class="lyric-mask"></div>
                  <div class="lyric-original"></div>
                </div>
            </div>
</div>
<audio id="audio" src="https://img2.oldkids.cn/upload/2025/08/03/blog_260848378_20250803161326665.mp3" autoplay loop></audio>

<script>
cat.onclick = () => audio.paused ? (audio.play(),ears.style.animationPlayState = 'running',p1.style.animationPlayState = 'running',p2.style.animationPlayState = 'running',baffisx.style.animationPlayState = 'running',baffidx.style.animationPlayState = 'running') : (audio.pause(),ears.style.animationPlayState = 'paused',p1.style.animationPlayState = 'paused',p2.style.animationPlayState = 'paused',baffisx.style.animationPlayState = 'paused',baffidx.style.animationPlayState = 'paused')
</script>

<script>
      // 歌词解析ksc歌词或lrc歌词
      const lrc = `时光匆匆如流水-影子
作词:未子夫
歌词由 梅竹 提供
作曲:李勇军
编曲:姜凯升
演唱:影子
☆★Lrc编辑 梅竹★☆
☆★协编 蓝菊★☆
. . . . . .
来到人世间受苦又受累
尝尽了人生百般滋味
一路坎坷雨打又风吹
回首这半生我太过狼狈
春去秋来 花开花枯萎
转眼我青丝 已经成了灰
想找个地方 好好醉一回
又害怕醉了没人可依偎
时光匆匆 岁月如流水
往事随风 一去不再回
不知不觉容颜已憔悴
我这辈子遭了太多罪
时光匆匆 岁月如流水
人到了中年 没路可以退
看遍了人间是是与非非
我若心碎 谁给我安慰
谁给我安慰
(Music)
春去秋来 花开花枯萎
转眼我青丝 已经成了灰
想找个地方 好好醉一回
又害怕醉了没人可依偎
时光匆匆 岁月如流水
往事随风 一去不再回
不知不觉容颜已憔悴
我这辈子遭了太多罪
时光匆匆 岁月如流水
人到了中年 没路可以退
看遍了人间是是与非非
我若心碎 谁给我安慰
谁给我安慰
(Music)
☆★梅竹谢谢欣赏★☆
=End=

`;
const audio = document.getElementById('audio');
      const lyrics = parseLyrics(lrc);
      const lyricMask = document.querySelector('.lyric-mask');
      const lyricOriginal = document.querySelector('.lyric-original');
      
      let currentIndex = -1;
      let currentLyric = null;
      
      // 解析歌词(支持两种格式)
      function parseLyrics(lrcText) {
            const lyrics = [];
            if (lrcText.includes('karaoke.add')) {
                const lineRegex = /karaoke\.add\('([^']+)', '([^']+)', '([^']+)', '([^']+)'\);/g;
                let match;
                while ((match = lineRegex.exec(lrcText)) !== null) {
                  const startTime = timeToMs(match);
                  const endTime = timeToMs(match);
                  const text = match.replace(/\[|\]/g, '').trim();
                  const durations = match.split(',').map(Number);
                  if (text) {
                        lyrics.push({startTime, endTime, text, durations});
                  }
                }
            }
            else if (lrcText.includes('[')) {
                const lines = lrcText.split('\n').filter(line => line.trim());
                lines.forEach((line, index) => {
                  const timeMatch = line.match(/\[(\d+:\d+\.\d+)\]/);
                  if (timeMatch) {
                        const timeStr = timeMatch;
                        const text = line.replace(/\[.*?\]/, '').trim();
                        if (text) {
                            const startTime = timeToMs(timeStr);
                            const nextLine = lines;
                            const nextTimeMatch = nextLine ? nextLine.match(/\[(\d+:\d+\.\d+)\]/) : null;
                            const endTime = nextTimeMatch ? timeToMs(nextTimeMatch) : startTime + 5000;
                            lyrics.push({
                              startTime,
                              endTime,
                              text,
                              durations: calculateCharDurations(text, startTime, endTime)
                            });
                        }
                  }
                });
            }
            return lyrics;
      }
      function calculateCharDurations(text, startTime, endTime) {
            const totalDuration = endTime - startTime;
            const charCount = text.length;
            const baseDur = Math.floor(totalDuration / charCount);
            const durations = new Array(charCount).fill(baseDur);
            const remainder = totalDuration % charCount;
            for (let i = 0; i < remainder; i++) {
                durations++;
            }
            return durations;
      }
      function timeToMs(timeStr) {
            const parts = timeStr.split(':');
            const minutes = parseInt(parts, 10);
            const secondsAndMs = parts.split('.');
            const seconds = parseInt(secondsAndMs, 10);
            const ms = parseInt(secondsAndMs || 0, 10);
            return minutes * 60 * 1000 + seconds * 1000 + ms;
      }
      function getCurrentLyricIndex(lyrics, currentTimeMs) {
            for (let i = 0; i < lyrics.length; i++) {
                if (currentTimeMs >= lyrics.startTime && currentTimeMs <= lyrics.endTime) {
                  return i;
                }
            }
            return -1;
      }
      function updateLyricDisplay(index) {
            if (index < 0 || index >= lyrics.length) return;
            currentIndex = index;
            currentLyric = lyrics;
            lyricOriginal.textContent = currentLyric.text;
            lyricMask.textContent = currentLyric.text;
            lyricMask.style.width = '0%';
      }
      function updateLyricMask(currentTimeMs) {
            if (!currentLyric) return;
            const lyricStartTime = currentLyric.startTime;
            const elapsed = currentTimeMs - lyricStartTime;
            const totalDuration = currentLyric.durations.reduce((sum, d) => sum + d, 0);
            let charIndex = 0;
            let accumulatedTime = 0;
            
            for (let i = 0; i < currentLyric.durations.length; i++) {
                accumulatedTime += currentLyric.durations;
                if (elapsed <= accumulatedTime) {
                  charIndex = i + 1;
                  break;
                }
            }
            
            if (elapsed >= totalDuration) {
                charIndex = currentLyric.text.length;
            }
            
            charIndex = Math.min(charIndex, currentLyric.text.length);
            
            const tempSpan = document.createElement('span');
            tempSpan.style.visibility = 'hidden';
            tempSpan.style.position = 'absolute';
            tempSpan.style.fontSize = '50px';
            tempSpan.style.fontWeight = '800';
            document.body.appendChild(tempSpan);
            
            const visibleText = currentLyric.text.substring(0, charIndex);
            tempSpan.textContent = visibleText;
            const width = tempSpan.offsetWidth;
            document.body.removeChild(tempSpan);
            
            lyricMask.style.width = `${width}px`;
      }
      
      // 监听更新歌词
      audio.addEventListener('timeupdate', () => {
            const currentTimeMs = audio.currentTime * 1000;
            const index = getCurrentLyricIndex(lyrics, currentTimeMs);
            
            if (index !== currentIndex) {
                updateLyricDisplay(index);
            }
            
            updateLyricMask(currentTimeMs);
      });
      updateLyricDisplay(0);
    </script>


   

       

杨帆 发表于 2025-8-18 21:30

厉害,这次猫咪的胡须都会动了!

谢谢亚伦老师经典分享与示范{:4_191:}

红影 发表于 2025-8-18 21:53

猫咪的眼睛还很有立体感呢。耳朵和胡须也会动,真漂亮。
歌词同步也好。欣赏亚伦老师好帖{:4_199:}

老谟深虑 发表于 2025-8-19 09:41

            欣赏老师的新作,点赞!
页: [1]
查看完整版本: 猫头播放器【时光匆匆如流水-影子】