亚伦影音工作室 发表于 2025-10-9 16:43

晚风-龙飘飘

本帖最后由 亚伦影音工作室 于 2025-10-18 12:23 编辑 <br /><br /><style>
    #bj {
      position: relative;
      width: 1286px;
      height: 680px;
      margin-left: -300px;
      margin-top: 10px;
      overflow: hidden;
      background: url(https://pic1.imgdb.cn/item/689714a158cb8da5c814a178.jpg) no-repeat center / cover;
    }
.intro {margin: 0px0px;
      width: 100%;
      height:100%;
      position: absolute;
background:url(https://pic1.imgdb.cn/item/689714a158cb8da5c814a178.jpg) no-repeat center / cover,linear-gradient(145deg, #ff0000, #000078, #00aa00, #000090);
background-size: cover;
background-blend-mode: hard-light;
animation: hue-rotate 3s linear infinite;
}
@keyframes hue-rotate {50%{ transform:scale(1); opacity: 0.1;filter: hue-rotate(360deg)}}


   .lrc {
      position: absolute;
      width: 500px;
      height: 460px;
      top: 45%;
      left: 70%;
      transform: translate(-50%, -50%); /* 容器整体居中 */
      overflow: hidden;
      text-align: center;
    }

   .lrc #ul {
      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 {filter:drop-shadow(#fff 1px 0px 1px);
      
      color: #000;
         font: 300 25px '华文新魏', sans-serif;
      
      transition: 0.1s all ease;
      list-style-type: none;
      text-align: center;
      padding: 0 0px;
      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: 200 28px '华文新魏', sans-serif;
      color:#800000;
      transform: scale(1.3)rotate(-720deg) translateY(-22%);/* 缩放效果 */
    }
   
    #bfq{   
      position:absolute;
      width: 450px;
      height:350px;overflow: hidden;
      background:#0000;
transform:scale(.4);bottom: -100px;
   left: -120px;z-index: 20;}
#cp{   
      position:absolute;
      width: 240px;border-radius: 50%;
      height:240px;animation: rotating 6s infinite linear;
      top:18%;background:repeating-radial-gradient(black, black 5px, #1C1C1C 6px, #1C1C1C 7px);
   cursor: pointer;
   left: 12%;z-index: 1;box-shadow:0px 0px 0px 1px #fff,0px 0px 0px 0px #880000;}
@keyframes rotating { to { transform: rotate(360deg); } }
.overlay {
content: '';
left: 50%;
top: 50%; transform: translate(-50%, -50%);
position: absolute;
width: 238px;
height: 238px;
background: linear-gradient(45deg, transparent, 40%, rgba(255,255,255,0.25), 60%, transparent);
border-radius: 50%;
}


.inner {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
box-shadow:0px 0px 0px 1px #eee,0px 0px 0px 2px #444;
background:#880000 url('') no-repeat center / cover;

border-radius: 50%;
}
.inner::before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 15px;
height: 15px;
background: #ccc;
border-radius: 50%;
}
#cz {position: absolute;
      top:6%; left:45%;z-index: 2;
      width: 150px;background: url('https://pic1.imgdb.cn/item/6688e0dad9c307b7e9a7a3e1.png')no-repeat center/85%;
      height: 300px;
      cursor: pointer;
}

.pink { transform:rotate(5deg);transform-origin: 100% 0%;}
.purple {transform-origin: 80% 0%;margin: -4px -18px;transform:rotate(-9deg);}
#prog {position: absolute;z-index: 8;
      width: 65%;
      height: 2px;background:#fff;
      cursor: pointer;
         bottom: 46px;
left:12%;
border-radius: 1px;}
#prog-bar {
            height: 100%;
            background: #FF0000;
            width: 0%;
      }

#tmsg {position: absolute;z-index: 8;
      font: 300 14px sans-serif;
      color: #fff;
         bottom: 42px;
      right: 40px;}

#fpp{position: absolute; bottom: 42px; right: 140px;filter:invert(0%)hue-rotate(360deg);
        width: 120px;cursor: pointer;background: url(https://pic1.imgdb.cn/item/68f315dcc5157e1a887fea24.png) no-repeat center / 120px 60px;
        height: 60px;z-index: 8; }
#fpp img{width: 100%;
        height: 100%;}

    </style>

<div id="bj">
<div class='intro'></div>

    <div class="lrc">
      <ul id="ul"></ul>
    </div>
   <div id="bfq">
<div id="cz"class="pink"></div>
<div id="cp"><div class="inner"></div><div class="overlay"></div></div>
</div>
<div id="prog" title="播放进度条"><div id="prog-bar"></div></div>
<div id='fpp'><img id="testImg" src="https://pic1.imgdb.cn/item/68e8ed85c5157e1a886292b4.gif" ></div>

<div id="tmsg">00:00|00:00</div>
</div>
</div>
<audio id="audio" src="https://upfile.mp3.wf/view.php/e5aae9d425312b135aa2127d83e71a5e.mp3" loop autoplay></audio>
<script>
    var lrc = `karaoke.add('00:01.430', '00:14.776', '晚风-龙飘飘', '1928,1928,1928,1928,1928,1928,1928,1280');
karaoke.add('00:15.430', '00:28.290', '词:西风', '3860,3860,3860,1280');
karaoke.add('00:30.878', '00:37.877', '夕阳下晚风凉', '1642,1306,931,869,971,1280');
karaoke.add('00:38.251', '00:43.465', '漫步走在山坡上', '761,490,405,470,860,948,1280');
karaoke.add('00:45.607', '00:49.527', '你也静静地', '1576,544,765,530,505');
karaoke.add('00:49.231', '00:52.618', '陪在我身旁', '906,315,462,424,1280');
karaoke.add('00:53.696', '00:58.207', '心底多舒畅', '561,785,889,996,1280');
karaoke.add('00:59.687', '01:07.392', '回想甜蜜的时光', '2314,466,885,905,1455,400,1280');
karaoke.add('01:07.677', '01:12.986', '我也不再黯然神伤', '750,485,435,430,486,857,586,1280');
karaoke.add('01:14.862', '01:21.813', '晚风歌出竹摇晃', '1616,803,900,881,969,965,817');
karaoke.add('01:21.522', '01:28.121', '把我吹进爱的梦乡', '768,494,1317,488,478,489,1285,1280');
karaoke.add('01:59.426', '02:06.582', '夕阳下晚风凉', '1855,1150,1046,827,998,1280');
karaoke.add('02:06.957', '02:12.120', '漫步走在山坡上', '699,454,480,450,918,882,1280');
karaoke.add('02:14.316', '02:18.115', '你也静静地', '1539,512,853,400,495');
karaoke.add('02:17.821', '02:21.338', '陪在我身旁', '965,574,508,190,1280');
karaoke.add('02:22.259', '02:26.905', '心底多舒畅', '522,939,925,980,1280');
karaoke.add('02:28.992', '02:36.035', '回想甜蜜的时光', '1658,472,934,874,1430,395,1280');
karaoke.add('02:36.335', '02:41.639', '我也不再黯然神伤', '745,471,414,819,301,735,539,1280');
karaoke.add('02:43.600', '02:50.517', '晚风歌出竹摇晃', '1720,495,955,1047,863,970,867');
karaoke.add('02:50.225', '02:55.859', '把我吹进爱的梦乡', '1234,1421,450,359,406,420,1144,200');
`;

    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);
</script>
<script>
      audio.addEventListener('timeupdate', () => {
            tmsg.innerText = toMin(audio.currentTime) + ' | ' + toMin(audio.duration);
      });
      
      function toMin(val) {
            if (!val) return '00:00';
            val = Math.floor(val);
            let min = parseInt(val / 60);
            let sec = parseFloat(val % 60);
            if (min < 10) min = '0' + min;
            if (sec < 10) sec = '0' + sec;
            return min + ':' + sec;
      }
      
      prog.onclick = (e) => { audio.currentTime = audio.duration * e.offsetX / prog.offsetWidth; }
      
      var progBar = document.getElementById('prog-bar');
      audio.addEventListener('timeupdate', () => {
            const percent = (audio.currentTime / audio.duration) * 100;
            progBar.style.width = percent + '%';
      });
      
      fpp.onclick =cp.onclick = cz.onclick = () => audio.paused ? (audio.play(), cz.classList.remove('purple'),intro.style.animationPlayState = 'running',image.play()) : (audio.pause(), cz.classList.add('purple'),intro.style.animationPlayState = 'paused',image.stop());
      
      cp.style.animationPlayState = audio.paused ? 'paused' : 'running';
      audio.addEventListener('playing', () => cp.style.animationPlayState = 'running');
      audio.addEventListener('pause', () => cp.style.animationPlayState = 'paused');

const intro= document.querySelector('.intro');
      
       </script>


<script>
if ('getContext' in document.createElement('canvas')) {
    HTMLImageElement.prototype.play = function() {
      if (this.storeCanvas) {
            // 移除存储的canvas
            this.storeCanvas.parentElement.removeChild(this.storeCanvas);
            this.storeCanvas = null;
            // 透明度还原
            image.style.opacity = '';
      }
      if (this.storeUrl) {
            this.src = this.storeUrl;   
      }
    };
    HTMLImageElement.prototype.stop = function() {
      var canvas = document.createElement('canvas');
      // 尺寸
      var width = this.width, height = this.height;
      if (width && height) {
            // 存储之前的地址
            if (!this.storeUrl) {
                this.storeUrl = this.src;
            }
            // canvas大小
            canvas.width = width;
            canvas.height = height;
            // 绘制图片帧(第一帧)
            canvas.getContext('2d').drawImage(this, 0, 0, width, height);
            // 重置当前图片
            try {
                this.src = canvas.toDataURL("image/gif");
            } catch(e) {
                // 跨域
                this.removeAttribute('src');
                // 载入canvas元素
                canvas.style.position = 'absolute';
                // 前面插入图片
                this.parentElement.insertBefore(canvas, this);
                // 隐藏原图
                this.style.opacity = '0';
                // 存储canvas
                this.storeCanvas = canvas;
            }
      }
    };
}
var image = document.getElementById("testImg");
</script>

樵歌 发表于 2025-10-9 19:44

这个歌词同步设计得很妙,一个个蹦出来。真不错!

马黑黑 发表于 2025-10-9 20:15

{:4_199:}

红影 发表于 2025-10-9 22:36

真漂亮的制作。
欣赏亚伦老师好帖{:4_199:}

小文 发表于 2025-10-9 22:39

高级!
页: [1]
查看完整版本: 晚风-龙飘飘