朵拉 发表于 2026-3-14 21:05

一路生花 TO:花潮论坛越来越红火!

<style>
      #bj {position: relative;
            width: 1286px;
            height: 720px;
            margin-left: -300px;
            margin-top: 10px;
            overflow: hidden;z-index:12345;
            background:radial-gradient(ellipse farthest-corner at center center, transparent 38%,#000 90%),url('https://upfile.mp3.wf/view.php/ba6ec9882a744c44f81bff8ae0973c6f.jpg'),linear-gradient(135deg, #e56420, #c22525, #3d9c31, #000078);
      }
      
      
      #lyricsCanvas {
            position: absolute;
            top: 30%;
            left: 2%;
            width: 800px;
            height: 450px;
            z-index: 2;
            
      }
      
         
      .controls-containe{
            position: absolute;
            bottom: 30px;
            left: 10px;
            width: 100%;
            display: flex;
            justify-content: center;
      }
      
      .controls {
            width: 85%;
            display: flex;
            align-items: center;
            gap: 10px;
            z-index: 4;
      }
      
      #progress {position:relative;
            bottom: 8px;
            flex-grow: 1;
            width: 100%;
            height: 4px;
            -webkit-appearance: none;
            background-color: transparent;
            outline: none;
      }
   

#progress::-webkit-slider-container {
    height: 18px;border-radius: 20px;
    overflow: hidden;
}
#progress::-webkit-slider-runnable-track {
    height: 4px;border-radius: 20px;
    background: #EEE;
}
#progress::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 20px;
    background: #880000;
    border: 1px solid transparent;
    margin-top: -4px;
    border-image: linear-gradient(#880000,#880000) 0 fill / 4 11 4 0 / 0px 0px 0 2000px;
}

      .play-btn {
            width: 90px;
            height: 30px;
            background-size: contain;
            background-repeat: no-repeat;
            background-position: center;
            background-color: transparent;
            border: none;
            cursor: pointer;
font: 400 24px '华文隶书', sans-serif;
            
            color: #eee;
            display: flex;
            align-items: center;
            justify-content: center;
      }
      
      .time-display {
         font: 300 20px '华文隶书', sans-serif;
            color: #eee;
            min-width: 110px;
            text-align: center;
      }
      
   </style>

   
   <divid="bj">
    <canvas id="lyricsCanvas" width="850" height="450"></canvas>
      
    <div class="controls-containe">
                            <div class="controls">
                              <span id="playBtn" class="play-btn">暂停</span>
<input type="range" id="progress" min="0" max="100" value="0"></input>
                              <span id="timeDisplay" class="time-display">00:00 / 00:00</span>
                              
                            </div>
                        </div>
      
</div>
<audio id="audio" src="https://upfile.mp3.wf/view.php/4f18553f2af06e355ad75a5ee6173456.mp3" autoplay loop></audio>
    <script>
      // 基础工具函数:时间格式化
      function formatTime(seconds) {
            const mins = Math.floor(seconds / 60);
            const secs = Math.floor(seconds % 60);
            return `${mins}:${secs < 10 ? '0' + secs : secs}`;
      }

      // 时间显示更新函数
      function updateTimeDisplay() {
            const currentTime = audio.currentTime;
            const duration = audio.duration || 0;
            timeDisplay.textContent = `${formatTime(currentTime)} / ${formatTime(duration)}`;
      }

      // DOM元素获取
      const dom = {
            lyricsCanvas: document.getElementById('lyricsCanvas'),
            
            playBtn: document.getElementById('playBtn'),
            progress: document.getElementById('progress'),
            timeDisplay: document.getElementById('timeDisplay')
            
      };
      const lyricsCtx = dom.lyricsCanvas.getContext('2d');
   
      
      // LRC歌词数据
      const lrcText = `
一路生花——温奕心

作词:宋普照

作曲:张博文

编曲:李师珏

录音:田亮

和声:张修峰

混音:茆博文

制作:朵拉




海上的晚霞像年少的画
铺在天空等海鸥衔走它
遥远的帆任风浪拍打
为梦再痛也不会害怕
远走的风沙去谁的天涯
春天可曾在哪里见过他
时间的手抚过了脸颊
他们谁都沉默不说话
我希望许过的愿望一路生花
护送那时的梦抵挡过风沙
指尖的樱花如诗写谁的韶华
疯狂的热爱夹带着文雅
我希望许过的愿望一路生花
将那雨中的人藏在屋檐下
岁月在冲刷逆流沧桑的喧哗
安静的夜晚你在想谁吗
远走的风沙去谁的天涯
春天可曾在哪里见过他
时间的手抚过了脸颊
他们谁都沉默不说话
我希望许过的愿望一路生花
护送那时的梦抵挡过风沙
指尖的樱花如诗写谁的韶华
疯狂的热爱夹带着文雅
我希望许过的愿望一路生花
将那雨中的人藏在屋檐下
岁月在冲刷逆流沧桑的喧哗
安静的夜晚你在想谁吗
我希望许过的愿望一路生花
护送那时的梦抵挡过风沙
指尖的樱花如诗写谁的韶华
疯狂的热爱夹带着文雅
我希望许过的愿望一路生花
将那雨中的人藏在屋檐下
岁月在冲刷逆流沧桑的喧哗
安静的夜晚你在想谁吗
安静的夜晚你在想谁吗
      `;

      //解析LRC歌词
      function parseLRC() {
            return lrcText.split('\n')
                .filter(line => line.trim() && line.includes('['))
                .map(line => {
                  const timeMatch = line.match(/\[(\d+):(\d+)\.(\d+)\]/);
                  if (!timeMatch) return null;
                  const time = parseInt(timeMatch) * 60 + parseInt(timeMatch) + parseInt(timeMatch)/100;
                  const text = line.replace(/\[.*?\]/g, '').trim();
                  return text ? { time, text } : null;
                })
                .filter(item => item)
                .sort((a, b) => a.time - b.time);
      }
      const lyricsList = parseLRC();
      let currentLyricIndex = -1;
      let floatingLyrics = [];

      class FloatingLyric {
            constructor(text) {
                this.text = text;
               
                this.x = Math.random() * (dom.lyricsCanvas.width - 100);
                this.y = Math.random() * (dom.lyricsCanvas.height - 30);
                this.vx = (Math.random() - 0.5) * 0.5;
                this.vy = (Math.random() - 0.5) * 0.5;
                this.opacity = 0;
                this.targetOpacity = 0.8 + Math.random() * 0.2;
                this.size = 30 + Math.random() * 7;
                this.color = `hsl(${Math.random() * 60}, 100%, 70%)`;
                this.life = 0;
                this.maxLife = 10;
                this.fadeInDuration = 1;
                this.fadeOutDuration = 2;
                this.isActive = true;
               
                lyricsCtx.font = `${this.size}px 微软雅黑`;
                this.textWidth = lyricsCtx.measureText(this.text).width;
            }

            update(deltaTime) {
                this.life += deltaTime;
                this.x += this.vx;
                this.y += this.vy;

               
                if (this.x < 10) {
                  this.x = 10;
                  this.vx *= -0.8;
                } else if (this.x + this.textWidth > dom.lyricsCanvas.width - 10) {
                  this.x = dom.lyricsCanvas.width - this.textWidth - 10;
                  this.vx *= -0.8;
                }
                if (this.y < this.size + 10) {
                  this.y = this.size + 10;
                  this.vy *= -0.8;
                } else if (this.y > dom.lyricsCanvas.height - 10) {
                  this.y = dom.lyricsCanvas.height - 10;
                  this.vy *= -0.8;
                }

               
                if (this.life < this.fadeInDuration) {
                  this.opacity = (this.life / this.fadeInDuration) * this.targetOpacity;
                } else if (this.life > this.maxLife - this.fadeOutDuration) {
                  this.opacity = ((this.maxLife - this.life) / this.fadeOutDuration) * this.targetOpacity;
                } else {
                  this.opacity = this.targetOpacity;
                }
            }

            draw() {
                if (this.opacity <= 0) return;
                lyricsCtx.save();
                lyricsCtx.globalAlpha = this.opacity;
                lyricsCtx.font = `${this.size}px 微软雅黑`;

               
                lyricsCtx.fillStyle = '#000';
                for (let i = 1; i <= 3; i++) {
                  lyricsCtx.fillText(this.text, this.x + i, this.y + i);
                }
               
                lyricsCtx.fillStyle = this.color;
                lyricsCtx.fillText(this.text, this.x, this.y);

            
                lyricsCtx.shadowBlur = 10;
                lyricsCtx.shadowColor = this.color;
                lyricsCtx.shadowOffsetX = 0;
                lyricsCtx.shadowOffsetY = 0;

                lyricsCtx.restore();
            }

            startFadeOut() {
                this.maxLife = this.life + this.fadeOutDuration;
                this.isActive = false;
            }
      }

      // 最后一句歌词特殊处理
      class LastLyric {
            constructor(text) {
                this.text = text;
                this.opacity = 0;
               
this.size = 30;
                this.color = "#fff666";
                this.isActive = false;
                this.fadeInDuration = 2;
                this.fadeOutDuration = 2;
                this.life = 0;

                this.maxLife = 30;
            }

            update(deltaTime) {
                this.life += deltaTime;
                if (!this.isActive) {
                  this.opacity = 0;
                  return;
                }

               
                if (this.life < this.fadeInDuration) {
                  this.opacity = (this.life / this.fadeInDuration);
                } else if (this.life > this.maxLife - this.fadeOutDuration) {
                  this.opacity = ((this.maxLife - this.life) / this.fadeOutDuration);
                  
                  if (this.opacity <= 0) {
                        this.deactivate();
                  }
                } else {
                  this.opacity = 1;
                }
            }

            draw() {
                if (!this.isActive || this.opacity <= 0) return;
                lyricsCtx.save();
                lyricsCtx.globalAlpha = this.opacity;
                lyricsCtx.font = `bold ${this.size}px 微软雅黑`;
                lyricsCtx.textAlign = 'center';
                lyricsCtx.textBaseline = '10';

               
                lyricsCtx.fillStyle = '#000';
                lyricsCtx.fillText(this.text, dom.lyricsCanvas.width / 2 + 2, dom.lyricsCanvas.height / 2 + 2);

               
                lyricsCtx.fillStyle = this.color;
                lyricsCtx.fillText(this.text, dom.lyricsCanvas.width / 2, dom.lyricsCanvas.height / 2);

               
                lyricsCtx.shadowBlur = 15;
                lyricsCtx.shadowColor = this.color;

                lyricsCtx.restore();
            }

            activate() {
                this.isActive = true;
                this.life = 0;
                this.opacity = 0;
            }

            deactivate() {
                this.isActive = false;
                this.opacity = 0;
                this.life = 0;
            }
      }
      const lastLyric = new LastLyric("欢迎回到我这里");
      let isLastLyricActive = false;

      

      //核心动画循环
      let lastTime = 0;
      function animate(timestamp) {
            if (audio.paused) {
                requestAnimationFrame(animate);
                return;
            }

            const deltaTime = (timestamp - lastTime) / 1000;
            lastTime = timestamp;
            lyricsCtx.clearRect(0, 0, dom.lyricsCanvas.width, dom.lyricsCanvas.height);
            

            const currentAudioTime = audio.currentTime;
            let targetLyricIndex = -1;

   
            for (let i = 0; i < lyricsList.length; i++) {
                if (currentAudioTime >= lyricsList.time) {
                  targetLyricIndex = i;
                } else {
                  
                  break;
                }
            }

      
            if (targetLyricIndex !== -1 && targetLyricIndex !== currentLyricIndex) {
               
                if (targetLyricIndex !== lyricsList.length - 1) {
                  lastLyric.deactivate();
                  isLastLyricActive = false;
                }

                const targetLyric = lyricsList;
                if (targetLyricIndex === lyricsList.length - 1) {
               
                  lastLyric.activate();
                  isLastLyricActive = true;
                } else {
                  
                  const newLyric = new FloatingLyric(targetLyric.text);
                  
                  const nextLyricTime = lyricsList?.time || (audio.duration || currentAudioTime + 5);
                  newLyric.maxLife = nextLyricTime - targetLyric.time + 1;
                  floatingLyrics.push(newLyric);
                }

                currentLyricIndex = targetLyricIndex;
            }

            
            floatingLyrics = floatingLyrics.filter(lyric => {
                lyric.update(deltaTime);
                lyric.draw();
               
                return lyric.life < lyric.maxLife && lyric.opacity > 0.01;
            });

            lastLyric.update(deltaTime);
            lastLyric.draw();

         
            if (audio.duration) {
                const progressPercent = (audio.currentTime / audio.duration) * 100;
                dom.progress.value = progressPercent;
                updateTimeDisplay();
            }

            requestAnimationFrame(animate);
      }

      // 播放/暂停按钮事件
      dom.playBtn.addEventListener('click', () => {
            if (audio.paused) {
                audio.play().then(() => {
                  
                  
                  dom.playBtn.textContent = '暂停';
                  
                  if (isLastLyricActive) {
                        lastLyric.deactivate();
                        isLastLyricActive = false;
                  }
                  
                  lastTime = performance.now();
                  requestAnimationFrame(animate);
                }).catch(e => console.error('音频播放失败:', e));
            } else {
               
                audio.pause();
               
                dom.playBtn.textContent = '播放';
            }
      });

      // 进度条拖动事件
      dom.progress.addEventListener('input', () => {
            if (!audio.duration) return;
            const targetTime = (dom.progress.value / 100) * audio.duration;
            audio.currentTime = targetTime;
            currentLyricIndex = -1;
            floatingLyrics = [];
         
            lastLyric.deactivate();
            isLastLyricActive = false;
            updateTimeDisplay();

         
            let targetLyricIndex = -1;
            for (let i = 0; i < lyricsList.length; i++) {
                if (targetTime >= lyricsList.time) {
                  targetLyricIndex = i;
                } else {
                  break;
                }
            }

            if (targetLyricIndex !== -1) {
                const targetLyric = lyricsList;
                if (targetLyricIndex === lyricsList.length - 1) {
                  lastLyric.activate();
                  isLastLyricActive = true;
                } else {
                  const newLyric = new FloatingLyric(targetLyric.text);
                  
                  newLyric.life = targetTime - targetLyric.time;
                  
                  const nextLyricTime = lyricsList?.time || (audio.duration || targetTime + 5);
                  newLyric.maxLife = nextLyricTime - targetLyric.time + 1;
                  
                  if (newLyric.life > newLyric.maxLife) {
                        newLyric.startFadeOut();
                  }
                  floatingLyrics.push(newLyric);
                }
            }

            
            dom.playBtn.textContent = audio.paused ? '播放' : '暂停';
      });

      // 音频结束事件
      audio.addEventListener('ended', () => {
            audio.currentTime = 0;
            audio.play();
            dom.playBtn.textContent = '暂停';
            
            currentLyricIndex = -1;
            floatingLyrics = [];
         
            lastLyric.deactivate();
            isLastLyricActive = false;
            lastTime = performance.now();
            requestAnimationFrame(animate);
      });

      // 音频加载完成事件
      audio.addEventListener('loadedmetadata', updateTimeDisplay);

      // 初始化自动播放
      audio.play().then(() => {
         
            dom.playBtn.textContent = '暂停';
            lastTime = performance.now();
            requestAnimationFrame(animate);
      }).catch(() => {
            console.log('自动播放被阻止,请点击播放按钮开始');
            dom.timeDisplay.textContent = '00:00 / --:--';
      });
    </script><

朵拉 发表于 2026-3-14 21:08

一路生花,祝花潮论坛越来越红火{:4_204:}{:4_204:}

红影 发表于 2026-3-14 23:35

好漂亮的制作,漂浮移动的歌词很奇妙。感谢朵宝的美好祝福{:4_187:}
这个没居中,需要再往左调一些。

小九 发表于 2026-3-14 23:39

欣赏朵拉好贴,非常好听!{:4_187:}

杨帆 发表于 2026-3-15 14:24

朵拉 发表于 2026-3-14 21:08
一路生花,祝花潮论坛越来越红火
晕~我这儿咋是这个效果呢https://s3.bmp.ovh/2026/03/15/1q7HnqJM.jpg

页: [1]
查看完整版本: 一路生花 TO:花潮论坛越来越红火!