亚伦影音工作室 发表于 2026-3-10 10:08

林栖 - 最真的梦

本帖最后由 亚伦影音工作室 于 2026-3-11 08:48 编辑 <br /><br /><style>@import url("https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap");
      .video-container {
            position: relative;
            width: 1186px;
            height: 520px; top: 0;
            left: -300px;background:url(https://file.uhsea.com/2603/9d50f866bc09655b18e83c8ad98f19091R.jpg)no-repeat center/cover;
            overflow: hidden;font-family: "Ma Shan Zheng","仿宋体","SimHei", "Arial", "sans-serif";
         
      }

   #lyricsCanvas {
            position: absolute;
            top: -50px;
            left: 0;
            width: 100%;
            height: 100%;      
            z-index: 25;font-family: "Ma Shan Zheng","仿宋体","SimHei", "Arial", "sans-serif";
            pointer-events: none;
            display: block;filter: hue-rotate(0deg)contrast(350%)brightness(150%);
      }

      .time-display-center {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 40;
                  color: #000;
            font-size: 20px;
            font-weight: 400;
         
            letter-spacing: 2px;
            pointer-events: none;
            white-space: nowrap;
         
            
            
            transition: text-shadow 0.2s;
            opacity: 1;
      }

   
          #player {position:absolute;top: 2%;z-index: 99;
            left: 83%;
width: 200px;
height: 200px;
display: grid;
        place-items: center;
animation: rot 8s linear infinite ;

}
@keyframes rot {to { transform: rotate(360deg);filter: hue-rotate(360deg); }}
#rect {position: absolute;
       
display: grid;
        place-items: center;
width:12%;
height: 40%;
clip-path: polygon(0 0, 50% 5%, 100% 0, 50% 50%, 100% 100%, 50% 95%, 0 100%, 50% 50%, 0 0);

}
#rect:nth-of-type(1) { background:#5500ff;transform: rotate(0deg);
}
#rect:nth-of-type(2) { background:#ff0000;transform: rotate(45deg);
}
#rect:nth-of-type(3) { background:#00aa00;transform: rotate(90deg);
}
#rect:nth-of-type(4) { background:#fff000;transform: rotate(135deg);
}
#canv {display: block; position: absolute;width:100%; height:250px; bottom: 0px; left: 0px;z-index:1; animation: sp 1s linear infinite;}
@keyframes sp {
      0% { filter:hue-rotate(360deg)contrast(250%)brightness(120%); }
}
   </style>

    <div class="video-container" id="videoContainer">
      
      

         <div id="player">
<spanid="rect"></span>
<spanid="rect"></span>
<spanid="rect"></span>
<spanid="rect"></span>
</div>
      <canvas id="lyricsCanvas" ></canvas>
<div id="timeDisplayCenter" class="time-display-center">00:00/00:00</div>
       <canvas id='canv'width="1300" height="300"></canvas>
<audio id="audioPlayer" preload="metadata" style="display: none;" src="https://s2.cldisk.com/sv-w8/audio/65/45/bb/3b5c023645788fee48a8e13f62d7573c/audio.mp3" loop crossOrigin="anonymous"></audio>
</div>

    <script>
      (function() {
            
            
            const audio = document.getElementById('audioPlayer');
            const canvas = document.getElementById('lyricsCanvas');
            const ctx = canvas.getContext('2d');
            const audioErrorNote = document.getElementById('audioErrorNote');
             const timeDisplay = document.getElementById('timeDisplayCenter');
      
            const container = document.getElementById('videoContainer');

// 歌词
            const lrcText = `今夜微风轻送
把我的心吹动
多少尘封的往日情
重回到我心中
往事随风飘送
把我的心刺痛
你是那美梦难忘记
深藏在记忆中
总是要经历百转和千回
才知情深意浓
总是要走遍千山和万水
才知何去何从
为何等到错过多年以后
才明白自己最真的梦
是否还记得我
还是已忘了我
今夜微风轻轻送
吹散了我的梦
今夜微风轻送
把我的心吹动
多少尘封的往日情
重回到我心中
往事随风飘送
把我的心刺痛
你是那美梦难忘记
深藏在记忆中
总是要历经百转和千回
才知情深意浓
总是要走遍千山和万水
才知何去何从
为何等到错过多年以后
才明白自己最真的梦
是否还记得我
还是已忘了我
今夜微风轻轻送
吹散了我的梦
`;

            function parseLrc(text) {
                const lines = text.split('\n');
                const result = [];
                const regex = /\[(\d+):(\d+\.\d+)\](.*)/;
                lines.forEach(line => {
                  const match = line.match(regex);
                  if (match) {
                        const min = parseInt(match, 10);
                        const sec = parseFloat(match);
                        const time = min * 60 + sec;
                        let content = match.trim();
                        if (content) result.push({ time, text: content });
                  }
                });
                result.sort((a, b) => a.time - b.time);
                return result;
            }
            const lyrics = parseLrc(lrcText);

            
            function resizeCanvas() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
            }
            window.addEventListener('resize', resizeCanvas);
            resizeCanvas();

         
      class SkewRainbowLyric {
                constructor(text, startTime) {
                  this.text = text;
                  this.startTime = startTime;
                  this.life = 0;
                  this.maxLife = 30.0;
                  this.startX = canvas.width / 2 + (Math.random() - 0.5) * 40;
                  this.startY = canvas.height * 0.72 + (Math.random() - 0.5) * 30;
                  this.targetX = canvas.width * (0.15 + Math.random() * 0.7);
                  this.targetY = canvas.height * (0.2 + Math.random() * 0.4);
                  this.startSize = 20 + Math.random() * 8;
                  this.targetSize = 85 + Math.random() * 200;
                  this.skewX = (Math.random() - 0.5) * 80;
                  this.skewY = -30 - Math.random() * 10;
                  this.skewFactor = 0;
                  this.opacity = 0;
                  this.hue = Math.random() * 360;
                  this.hueSpeed = 20 + Math.random() * 30;
                  this.twinklePhase = Math.random() * 2 * Math.PI;
                  this.twinkleSpeed = 1.5 + Math.random() * 2;
                }

                update(delta) {
                  this.life += delta;
                  if (this.life > this.maxLife) return false;
                  const progress = Math.min(this.life / this.maxLife, 1);
                  const easeOut = t => 1 - Math.pow(1 - t, 1.5);
                  const eased = easeOut(progress);
                  this.x = this.startX + (this.targetX - this.startX) * eased;
                  this.y = this.startY + (this.targetY - this.startY) * eased;
                  this.size = this.startSize + (this.targetSize - this.startSize) * eased;
                  this.skewFactor = Math.sin(progress * Math.PI) * 0.6;
                  const fadeInEnd = 0.2;
                  const fadeOutStart = 0.8;
                  if (progress < fadeInEnd) {
                        this.opacity = progress / fadeInEnd;
                  } else if (progress > fadeOutStart) {
                        this.opacity = 1 - (progress - fadeOutStart) / (1 - fadeOutStart);
                  } else {
                        this.opacity = 1;
                  }
                  this.hue += this.hueSpeed * delta;
                  if (this.hue > 360) this.hue -= 360;
                  this.twinklePhase += this.twinkleSpeed * delta;
                  return true;
                }

                draw(ctx) {
                  if (this.opacity <= 0.01) return;
                  ctx.save();
                  const currentSkewX = this.skewX * this.skewFactor * 0.015;
                  const currentSkewY = this.skewY * this.skewFactor * 0.015;
                  ctx.transform(1, currentSkewY, currentSkewX, 1, 0, 0);
                  ctx.translate(this.x, this.y);
                  ctx.font = `400 ${this.size}px"Ma Shan Zheng","仿宋体","SimHei", "Arial", "sans-serif"`;
                  ctx.textAlign = 'center';
                  ctx.textBaseline = '';
                  const mainColor = `hsl(${this.hue}, 80%, 50%)`;
                  const twinkle = 0.7 + 0.3 * Math.sin(this.twinklePhase);
                  const shadowBlur = 18 + 12 * twinkle;
                  const shadowColor = ``;
                  ctx.shadowBlur = shadowBlur;
                  ctx.shadowColor = shadowColor;
                  ctx.shadowOffsetX = 0;
                  ctx.shadowOffsetY = 0;
                  ctx.strokeStyle = 'hsl(${this.hue}, 0%, 0%)';
                  ctx.lineWidth = '1';
                  ctx.strokeText(this.text, 0, 0);
                  ctx.fillStyle = mainColor;
                  ctx.globalAlpha = this.opacity;
                  ctx.fillText(this.text, 0, 0);
                  ctx.shadowBlur = shadowBlur + 15;
                  ctx.shadowColor = ``;
                  ctx.fillText(this.text, 0, 0);
                  ctx.restore();
                }
            }

            let activeLyrics = [];
            let lastLyricIndex = -1;

            function spawnLyricForTime(currentTime) {
                let idx = lyrics.findIndex(l => l.time > currentTime);
                if (idx === -1) idx = lyrics.length;
                const currentIndex = idx - 1;
                if (currentIndex < 0) return;
                if (currentIndex === lastLyricIndex) return;
                lastLyricIndex = currentIndex;
                activeLyrics = [];
                const lyric = lyrics;
                const newLyric = new SkewRainbowLyric(lyric.text, lyric.time);
                activeLyrics.push(newLyric);
            }

            function resetLyrics() {
                activeLyrics = [];
                lastLyricIndex = -1;
            }

            let timeHue = 0;

            function formatTime(seconds) {
                if (isNaN(seconds)) return '00:00';
                const mins = Math.floor(seconds / 60);
                const secs = Math.floor(seconds % 60);
                return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
            }

         
         function updateTimeDisplay() {
                if (!audio.duration) return;
                const current = audio.currentTime;
                const duration = audio.duration;
                timeDisplay.textContent = `${formatTime(current)} / ${formatTime(duration)}`;
            }

            function updateTimeColor() {
                timeDisplay.style.color = `hsl(${timeHue}, 0%, 0%)`;
                timeDisplay.style.textShadow = ``;
            }
         

            audio.addEventListener('timeupdate', () => {
                updateTimeDisplay();
                if (lyrics.length) {
                  spawnLyricForTime(audio.currentTime);
                }
            });

            audio.addEventListener('loadedmetadata', () => {
                updateTimeDisplay();
            });

            audio.addEventListener('error', () => {
                audioErrorNote.style.display = 'block';
            });

            audio.addEventListener('canplay', () => {
                audioErrorNote.style.display = 'none';
            });

            audio.addEventListener('ended', () => {
                resetLyrics();
                updateTimeDisplay();
               
            });

         window.addEventListener('load', () => {
                audio.load();
                audio.play().catch(e => {
                     setPausedState(true);
                  
                });
               
                if (audio.paused) {
                  setPausedState(true);
                }
            });

            let lastTimestamp = 0;
            function animate(now) {
                if (!lastTimestamp) lastTimestamp = now;
                const delta = Math.min(0.1, (now - lastTimestamp) / 1000);
                lastTimestamp = now;

                timeHue += delta * 15;
                if (timeHue > 360) timeHue -= 360;
                updateTimeColor();

                ctx.clearRect(0, 0, canvas.width, canvas.height);

                const isPlaying = !audio.paused;
                activeLyrics = activeLyrics.filter(lyric => {
                  if (isPlaying) {
                        const keep = lyric.update(delta);
                        if (keep) lyric.draw(ctx);
                        return keep;
                  } else {
                        lyric.draw(ctx);
                        return true;
                  }
                });

                requestAnimationFrame(animate);
            }
            requestAnimationFrame(animate);
      })();

player.onclick = () => audioPlayer.paused ? (audioPlayer.play(),player.style.animationPlayState = 'running') : (audioPlayer.pause(),player.style.animationPlayState = 'paused');
    </script>
<script>
(function () {

        let Act = new AudioContext();

        let audSrc = Act.createMediaElementSource(audioPlayer);

        let analyser = Act.createAnalyser();

        audSrc.connect(analyser);

        analyser.connect(Act.destination);

        let ctx = canv.getContext('2d');

        let width = canv.width;

        let height = canv.height;

        let ppColor = ctx.createLinearGradient(250,200,250,0);

        ppColor.addColorStop(0.4, '#00ff00');

        let ppNum = 1300;

        let voiceHeight = new Uint8Array(analyser.frequencyBinCount);



        (function draw() {

                analyser.getByteFrequencyData(voiceHeight);

                let step = Math.round(voiceHeight.length / ppNum);

                ctx.clearRect(5, 5, width, height);

                for (let j = 0; j < ppNum; j++) {

                        let audiheighteight = voiceHeight;

                        ctx.fillStyle = ppColor;

                        ctx.fillRect(width / 2+ (j * 4), height, 3, -audiheighteight);

                        ctx.fillRect(width / 2- (j * 4), height, 3, -audiheighteight);

                }

                window.requestAnimationFrame(draw);

        })();
})();
</script>

梦油 发表于 2026-3-10 10:43

欣赏佳作,问候亚伦。

杨帆 发表于 2026-3-10 15:50

频谱漂亮,形式新颖,切换顺畅,谢谢亚伦老师精彩分享{:4_176:}

雨季工作室 发表于 2026-3-10 16:44

欣赏亚伦老师制作漂亮分享!

红影 发表于 2026-3-10 19:12

漂亮的变得频谱和变色飘飞的同步歌词。
欣赏亚伦老师好帖{:4_199:}
页: [1]
查看完整版本: 林栖 - 最真的梦