亚伦影音工作室 发表于 2025-8-5 15:44

刀郎-雨中飘荡的回忆【ksc歌词】

本帖最后由 亚伦影音工作室 于 2025-11-24 08:53 编辑 <br /><br /><style>
    #bj {
      position: relative;
      width: 1286px;
      height: 680px;
      margin-left: -300px;
      margin-top: 150px;
      overflow: hidden;
      background:#000;
    }
.intro {margin: 0px0px;
      width: 100%;
      height:100%;
      position: absolute;
background: url(https://pic1.imgdb.cn/item/6824a1fc58cb8da5c8f1b5a2.jpg), linear-gradient(45deg, #e56420, #c22525, #3d9c31, #37bbde);
background-size: cover;
background-blend-mode: hard-light;
animation: hue-rotate 3s linear infinite;
}
@keyframes hue-rotate {
from {
   filter: hue-rotate(0);
}
to {
   filter: hue-rotate(360deg);
}
}
   .lrc {
      position: absolute;
      width: 100%;
      height: 60px; /* 只显示一行歌词高度 */
      top: 90%;
      left: 50%;
      transform: translate(-50%, -50%); /* 容器整体居中 */
      overflow: hidden;
      text-align: center;
    }

   .lrc #ul {filter:drop-shadow(#FFFFFF 1px 0 0)drop-shadow(#FFFFFF 0 1px 0)drop-shadow(#FFFFFF -1px 0 0) drop-shadow(#FFFFFF 0 -1px0);
      width: 100%;
      padding: 0;
      list-style: none;
      transition: 0.1s all ease;
      margin: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

   .lrc #ul li {
      font-size: 44px;
      color: #000;
      font-family: "华文隶书", "Microsoft YaHei", sans-serif;
      font-weight:500;
      transition: 0.1s all ease;
      list-style-type: none;
      text-align: center;
      padding: 0 10px;
      height: 60px;
      line-height: 60px;
      cursor: pointer;
      white-space: nowrap; /* 防止歌词换行 */
    }

.lrc #ul li span {
      margin: 0 5px;
      transform-origin: center center; /* x轴和y轴均以中心为原点 */
      transition: all 0.1s cubic-bezier(0.34, 1.56, 0.64, 1); /* 缓动函数让动画更自然 */
      display: inline-block; /* 确保transform-origin生效 */
    }
   
   .lrc #ul li span.active {
      font-family: "华文隶书", "Microsoft YaHei", sans-serif;
      font-weight: 500;
      font-size: 50px;
      color: red;
      transform: scale(1.2)rotate(-360deg); /* 缩放效果 */
    }
   
      
#pa { top:50px; left: 80px; width: 100%; height: 460px; position: absolute; }
    .text {
      margin: 10px;
      font: bold 40px 'Microsoft YaHei', sans-serif;
      color: #bbb;
      text-shadow: 0 0 1px #000, 2px 2px 6px #000;
      display: inline-block;
    }
    .ani { animation: circ 2s linear; }
    @keyframes circ {
      to { transform: rotate(720deg); }
    }
      .stop .ani{animation-play-state: paused;}
   

</style>

<div id="bj">

<div class='intro'></div>


      <div class="lrc">

      <ul id="ul"></ul>
   
   </div>




<div id="testImg">
<div id="pa"></div>
</div>
</div>
<audio id="audio" src="https://s2.ananas.chaoxing.com/sv-w9/audio/41/4d/89/46a43ceac13d5a2118d56dc2798bc9ad/audio.mp3" loop autoplay></audio>
<script>
    var lrc = `karaoke.add('00:00.000', '00:12.236', '刀郎-雨中飘荡的回忆', '1019,1020,1020,1019,1020,1020,1020,1019,1020,1020,1020,1019');
karaoke.add('00:12.236', '00:17.335', '作词:刀郎', '1020,1020,1019,1020,1020');
karaoke.add('00:17.335', '00:22.433', '作曲:刀郎', '1020,1019,1020,1020,1019');
karaoke.add('00:22.434', '00:26.764', '今夜又下着小雨', '510,410,350,490,370,920,1280');
karaoke.add('00:28.866', '00:34.166', '小雨它一点一点滴滴', '530,330,500,310,480,290,500,1170,1190');
karaoke.add('00:35.408', '00:39.708', '一点点一滴滴它飘来飘去', '370,460,490,300,380,390,440,420,360,450,240');
karaoke.add('00:41.032', '00:46.506', '像去年那场相遇', '420,640,1804,390,370,570,1280');
karaoke.add('00:48.336', '00:52.576', '那天也下着小雨', '410,490,380,430,340,910,1280');
karaoke.add('00:54.886', '00:58.976', '雨中的你是那样美丽', '350,470,450,330,430,420,420,1200,20');
karaoke.add('01:01.336', '01:05.786', '我问你是否喜欢和我一起', '450,390,380,450,360,400,470,400,440,270,440');
karaoke.add('01:07.056', '01:12.016', '你笑着无语', '280,500,2050,850,1280');
karaoke.add('01:13.086', '01:18.666', '那一天这世界是多么美丽', '460,340,1290,300,680,560,440,430,410,650,20');
karaoke.add('01:19.546', '01:25.316', '尽管天上的小雨一点一滴滴', '460,410,1150,500,720,540,450,270,520,280,140,330');
karaoke.add('01:26.106', '01:32.036', '空气中飘荡着你那芬芳的气息', '430,360,1240,400,420,440,320,420,400,450,180,440,430');
karaoke.add('01:32.506', '01:38.336', '任小雨落在我的头顶', '410,520,1120,410,850,400,410,430,1280');
karaoke.add('01:39.016', '01:44.766', '今夜里我又站在雨里', '490,330,1250,400,780,430,440,350,1280');
karaoke.add('01:45.506', '01:51.976', '任感情在小雨里飘来飘去', '430,380,1260,340,710,590,360,430,390,630,950');
karaoke.add('01:51.996', '01:58.416', '我问我自己是否还在爱着你', '460,390,1230,410,780,450,370,410,440,340,490,650');
karaoke.add('01:58.436', '02:03.436', '就这样轻易地放弃', '450,450,1180,540,280,390,1210,500');
karaoke.add('02:09.448', '02:13.768', '今夜又下着小雨', '500,420,340,490,360,930,1280');
karaoke.add('02:15.920', '02:20.820', '仿佛又看到你的背影', '480,400,360,460,410,350,470,1790,180');
karaoke.add('02:22.428', '02:26.998', '我想要告诉自己不再爱你', '360,500,380,410,390,380,440,350,520,370,470');
karaoke.add('02:28.098', '02:36.414', '但奈何这滴滴小雨', '410,550,3846,460,650,500,620,1280');
karaoke.add('03:04.946', '03:10.766', '今夜里我又站在雨里', '500,340,1220,420,810,420,440,390,1280');
karaoke.add('03:11.476', '03:17.826', '任感情在小雨里飘来飘去', '410,380,1230,350,700,620,390,420,360,630,860');
karaoke.add('03:17.976', '03:24.196', '我问我自己是否还在爱着你', '450,370,1210,400,790,430,400,390,450,340,460,530');
karaoke.add('03:24.746', '03:30.106', '就这样轻易地放弃', '120,440,1190,520,280,400,1200,1210');
karaoke.add('03:32.100', '03:36.420', '今夜又下着小雨', '500,410,350,480,370,930,1280');
karaoke.add('03:38.570', '03:43.470', '仿佛又看到你的背影', '480,390,370,460,400,350,470,1540,440');
karaoke.add('03:45.072', '03:49.732', '我想要告诉自己不再爱你', '360,510,380,400,390,380,440,350,520,360,570');
karaoke.add('03:50.744', '03:59.066', '但奈何这滴滴小雨', '430,520,3852,470,640,490,640,1280');
karaoke.add('04:00.526', '04:08.842', '但奈何这滴滴小雨', '400,540,3856,460,640,510,630,1280');
`;

    let lrcArr = lrc.split('\n');
    let result = [];
    var audio = document.querySelector("#audio"),
      ul = document.querySelector("#ul"),
      container = document.querySelector(".lrc");

    const lrcRegex = /karaoke\.add\('([\d:/.]+)',\s*'([\d:/.]+)',\s*'([^']*)'/;
    for (let i = 0; i < lrcArr.length; i++) {
      const line = lrcArr.trim();
      if (!line) continue;
      const match = line.match(lrcRegex);
      if (!match) continue;

      const startTimeStr = match;
      const endTimeStr = match;
      const lineText = match.trim();
      if (!lineText) continue;

      const startTime = parseTime(startTimeStr);
      const endTime = parseTime(endTimeStr);
      const lineDuration = endTime - startTime;

      const words = lineText.split('');
      const wordCount = words.length;
      if (wordCount === 0) continue;

      const wordDuration = lineDuration / wordCount;
      const lineWords = [];
      words.forEach((word, index) => {
            lineWords.push({
                time: startTime + index * wordDuration,
                text: word
            });
      });
      result.push(lineWords);
    }

    function parseTime(timeStr) {
      const = timeStr.split(':');
      return parseInt(minutes, 10) * 60 + parseFloat(seconds);
    }

    function getCurrentLineIndex() {
      const currentTime = audio.currentTime;
      for (let i = 0; i < result.length; i++) {
            const line = result;
            if (currentTime >= line.time &&
                (i === result.length - 1 || currentTime < result.time)) {
                return i;
            }
      }
      return -1;
    }

    function createLyricElements() {
      const frag = document.createDocumentFragment();
      result.forEach((lineWords, lineIndex) => {
            const li = document.createElement("li");
            lineWords.forEach(wordObj => {
                const span = document.createElement("span");
                span.textContent = wordObj.text;
                span.dataset.time = wordObj.time;
                li.appendChild(span);
            });
            li.addEventListener('click', () => {
                audio.currentTime = lineWords.time;
            });
            frag.appendChild(li);
      });
      ul.appendChild(frag);
    }

    createLyricElements();

    const liHeight = 60;
    const visibleLines = 1;
    let prevLineIndex = -1;

    function syncLyric() {
      const currentLineIndex = getCurrentLineIndex();
      if (currentLineIndex === -1) return;

      const scrollOffset = currentLineIndex * liHeight;
      ul.style.transform = `translateY(-${scrollOffset}px)`;

      if (prevLineIndex!== -1 && prevLineIndex!== currentLineIndex) {
            const prevLi = ul.children;
            if (prevLi) {
                prevLi.querySelectorAll('span.active').forEach(span => {
                  span.classList.remove('active');
                });
            }
      }

      const currentLi = ul.children;
      const currentLine = result;
      const currentTime = audio.currentTime;

      currentLine.forEach((wordObj, wordIndex) => {
            const span = currentLi.children;
            const isActive = currentTime >= wordObj.time &&
                            (wordIndex === currentLine.length - 1 ||
                           currentTime < currentLine.time);
            
            if (isActive) {
                span.classList.add('active');
            } else {
                span.classList.remove('active');
            }
      });

      prevLineIndex = currentLineIndex;
    }

    audio.addEventListener("timeupdate", syncLyric);
    const intro= document.querySelector('.intro');
    bj.onclick = () => {audio.paused ? (audio.play()) : (audio.pause());}
letmState = () => {
          audio.paused ?(intro.style.animationPlayState = 'paused',testImg.classList.add('stop')) : (intro.style.animationPlayState = '',testImg.classList.remove('stop')) ;
      };
audio.onplaying = audio.onpause = () => mState();
</script>
<script>
    const txtAr = '雨中飘荡的回忆'.split('');
    let spans = [];
    txtAr.forEach( (t,k) => {
      const s = document.createElement('span');
      s.textContent = t;
      s.className = k === 0 ? 'text ani' : 'text';
      spans.push(s);
      s.onanimationend = () => {
            s.classList.remove('ani');
            spans[(k+1) % txtAr.length].classList.add('ani');
      };
      pa.appendChild(s);
    });
</script>

杨帆 发表于 2025-8-5 19:06

漂亮!谢谢亚伦老师经典示范与分享{:4_190:}

红影 发表于 2025-8-5 19:35

标题字和歌词字都一样是旋转的,相互呼应。真漂亮,好构思{:4_199:}

红影 发表于 2025-8-5 19:36

发现同步歌词会高亮文字,并且高亮字会自动变成正向,高亮的瞬间不再旋转。真神奇{:4_199:}

红影 发表于 2025-8-5 19:38

欣赏亚伦老师好帖,很赞{:4_199:}

樵歌 发表于 2025-8-5 20:28

非常有创意!

梦油 发表于 2025-8-5 21:02

欣赏精彩,问候亚伦。
页: [1]
查看完整版本: 刀郎-雨中飘荡的回忆【ksc歌词】