亚伦影音工作室 发表于 2025-8-23 21:08

学猫叫【变脸猫】

本帖最后由 亚伦影音工作室 于 2025-8-25 14:34 编辑 <br /><br /><style>
#bj { position: relative;
            width: 1280px;
            height: 720px;
            margin-left: -300px;
            margin-top: 10px;
            overflow: hidden;z-index:12345;
         background:#000 url('https://pic.3gbizhi.com/uploadmark/20250720/d8ec208952bd584a7bae0d5025f3c825.webp') no-repeat center / cover;
      --state: paused;}
#ppc{z-index:1;position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
overflow: hidden;
}

#ppc span {
width: 40vmin;
height: 40vmin;
border-radius: 40vmin;
backface-visibility: hidden;
position: absolute;
animation: move var(--state);
animation-duration: 50;
animation-timing-function: linear;
animation-iteration-count: infinite;
}

#ppc span:nth-child(0) {
color: #00ff00;
top: 96%; left: 54%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 4vw -24vh;
box-shadow: -80vmin 0 10.416025873807692vmin currentColor;
}

#ppc span:nth-child(1) {
color: #00ff00;
top: 75%;
left: 69%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 7vw 17vh;
box-shadow: 80vmin 0 10.632336952027394vmin currentColor;
}

#ppc span:nth-child(2) {
color: #ff0000;
top: 59%;
left: 72%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 1vw -1vh;
box-shadow: -80vmin 0 10.547582314554877vmin currentColor;
}

#ppc span:nth-child(3) {
color: #00ffff;
top: 42%;
left: 70%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: -7vw 13vh;
box-shadow: 80vmin 0 10.157682633588278vmin currentColor;
}

#ppc span:nth-child(4) {
color: #ffff00;
top: 77%;
left: 32%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 15vw -21vh;
box-shadow: 80vmin 0 10.353571357073374vmin currentColor;
}

#ppc span:nth-child(5) {
color: #880000;
top: 46%;
left: 15%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 25vw 21vh;
box-shadow: 80vmin 0 10.141292598615633vmin currentColor;
}

#ppc span:nth-child(6) {
color: #00ffff;
top: 25%;
left: 9%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 9vw -17vh;
box-shadow: -80vmin 0 10.509291298036052vmin currentColor;
}

#ppc span:nth-child(7) {
color: #00ff00;
top: 51%;
left: 97%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: -1vw 2vh;
box-shadow: -80vmin 0 10.643941445103458vmin currentColor;
}

#ppc span:nth-child(8) {
color: #000078;
top: 38%;
left: 55%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 18vw -6vh;
box-shadow: 80vmin 0 10.139110524828311vmin currentColor;
}

#ppc span:nth-child(9) {
color: #ff0000;
top: 61%;
left: 66%;
animation-duration: 6s;
animation-delay: -1s;
transform-origin: 4vw 6vh;
box-shadow: 80vmin 0 10.111486137252184vmin currentColor;
}

@keyframes move {
100% {
transform: translate3d(0, 0, 1px) rotate(360deg);
}

@keyframes an-pupils {
    from {transform: rotate(0deg);
      left: 60px;
    }
    to {transform: rotate(360deg);
      left: 0px;
    }
}
</style>
<style>
.lyrics{margin: 0;z-index:20;
            top: 91%;
                left: 50%;
    transform: translate(-50%, -50%);
            height: 100px; /* 调整高度,只容纳当前歌词 */
                 text-align: center;
             position: absolute;
      }
            .lyric-line{
            width: 100%;
            position: relative;
            height: 60px;
            overflow: visible;
   font:600 45px 'FZYaoti', 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: #ff0000;
            height: 100%;
            white-space: nowrap;
      }

      .lyric-original {
             color: #55aa00;
            white-space: nowrap;
            }
</style>
<style>
@keyframes an-ears {
    from {
       top:0;
    }
    to {
       top:25px;
    }
}
@keyframes an-pupils {
    from {transform: rotate(0deg);
      left: 40px;
    }
    to {transform: rotate(360deg);
      left: 0px;
    }
}
#cat {position: relative;
width: 480px;z-index: 20;top: 300px;
left: -5%;transform:scale(0.4);

animation: rot 1s linear infinite var(--state);}
@keyframes rot {
    from {transform:scale(0.4);filter: hue-rotate(0deg);}
    to {transform:scale(0.3);filter: hue-rotate(360deg); }
}
#head {
        width: 400px;
        height: 370px;
        background-color: #DAA520;
        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 #DAA520;
        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: #eee;
        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: #fff;
        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:#fff transparent transparent transparent;
border-radius: 60%/30px 30px 0 0;

}

</style>

<div id="bj">
<div class="lyrics">
            <div class="lyric-line">
                  <div class="lyric-mask"></div>
                  <div class="lyric-original"></div>
                </div>
            </div>

<div id="ppc">

   <span ></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>

   <span></span>
</div>
<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>
<audio id="audio" src="https://img3.oldkids.cn/upload/2025/08/23/blog_260855907_20250823210619279.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')
var mState = () => {
      bj.style.setProperty('--state', audio.paused ? 'paused' : 'running');
       };
audio.onplaying = audio.onpause = () => mState();
</script>
<script>
      // 歌词解析ksc歌词或lrc歌词
      const lrc = `学猫叫 - 小潘潘 (GorDoN)/小峰峰 (Cheney.F)
词:小峰峰
曲:小峰峰
编曲:吕宏斌/塞米七
和声:小峰峰
混音:陈秋洁
制作人:小峰峰
唱片:麦袭时代
OP:百纳娱乐
经纪:亿人传媒
女:
我们一起学猫叫
一起喵喵喵喵喵
在你面前撒个娇
哎呦喵喵喵喵喵
我的心脏砰砰跳
迷恋上你的坏笑
你不说爱我我就喵喵喵
男:
每天都需要你的拥抱
珍惜在一起的每分每秒
你对我多重要
我想你比我更知道
你就是我的女主角
女:
有时候我懒的像只猫
脾气不好时又张牙舞爪
你总是温柔的
能把我的心融化掉
我想要当你的小猫猫
合:
我们一起学猫叫
一起喵喵喵喵喵
在你面前撒个娇
哎呦喵喵喵喵喵
我的心脏砰砰跳
迷恋上你的坏笑
你不说爱我我就喵喵喵
我们一起学猫叫
一起喵喵喵喵喵
我要穿你的外套
闻你身上的味道
想要变成你的猫
赖在你怀里睡着
每天都贪恋着你的好
女:
有时候我懒的像只猫
脾气不好时又张牙舞爪
你总是温柔的
能把我的心融化掉
我想要当你的小猫猫
合:
我们一起学猫叫
一起喵喵喵喵喵
在你面前撒个娇
哎呦喵喵喵喵喵
我的心脏砰砰跳
迷恋上你的坏笑
你不说爱我我就喵喵喵
我们一起学猫叫
一起喵喵喵喵喵
我要穿你的外套
闻你身上的味道
想要变成你的猫
赖在你怀里睡着
每天都贪恋着你的好
我们一起学猫叫
一起喵喵喵喵喵
在你面前撒个娇
哎呦喵喵喵喵喵
我的心脏砰砰跳
迷恋上你的坏笑
你不说爱我我就喵喵喵
我们一起学猫叫
一起喵喵喵喵喵
我要穿你的外套
闻你身上的味道
想要变成你的猫
赖在你怀里睡着
每天都贪恋着你的好

`;
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-23 21:20

哇,新的变脸猫诞生了!

谢谢亚伦老师精彩分享{:4_191:}

朵拉 发表于 2025-8-23 21:25

亚伦老师 好创意,欣赏咯{:4_178:}

红影 发表于 2025-8-23 22:09

这个猫咪小播能斌阿瑟还能变幻大小,好漂亮啊。
欣赏亚伦老师好帖{:4_199:}
页: [1]
查看完整版本: 学猫叫【变脸猫】