亚伦影音工作室 发表于 2025-10-25 10:09

我等风等雨不等你

本帖最后由 亚伦影音工作室 于 2025-10-25 10:50 编辑 <br /><br /><style>

#spectrum {
    position: absolute;
    left: 20px;
    top: 660px;
    width: 120px;
    height: 40px;
    z-index: 2;
}
.pa {
    --state: running;
    position: relative;
    display: grid;
    place-items: center;
    width: 1024px;
    height: 640px;
   
    z-index: 1;
}
.h1 {
    position: absolute;
    top: 45px;
    left: 400px;
    color: #fff;
   font: bold 2.6em cursive;
    margin-bottom: 20px;
   
    letter-spacing: 2px;
      filter: drop-shadow(1px 1px 0px hsla(0, 0%, 0%, .95));
    z-index: 2;
}


#mama {
   position: relative;
    left: -300px;
    top: 0;
    width: 1186px;
    height: 720px;
    background: black url('https://pic1.imgdb.cn/item/6844eb3b58cb8da5c83985dc.webp') no-repeat center/ cover;
    overflow: hidden;
   
}

.player {
    position: absolute;
    width: 200px;
    height: 200px;
    left: 50px;
    top: 80px;
    cursor: pointer;
    z-index: 2;
   
}

.player:hover {
    filter: brightness(1.2);
    transition: 0s;
}

.prog {
    position: absolute;
    left: 195px;
    bottom: 20px;
    width: 860px;
    height: 2px;
    background: var(--bg1);
    display: grid;
    place-items: center;
    cursor: pointer;
    z-index: 3;
    --prog: 0%;
    --bg1: #000;
    --bg2: #ff0000;
    --color: #000;
    opacity: 0.9;
}

.prog::before {
    position: absolute;
    content: attr(data-tt);
    left: -50px;
    right: -50px;
    text-align:justify;
    text-align-last: justify;
    font-size: 14px;
    color: var(--color);
}

.prog::after {
    position: absolute;
    content:'';
    left: calc(var(--prog) - 6px);
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--bg2);
}

.lrc {
    position: absolute;
    left: 81%;
    transform: translateX(-50%);
    bottom: 65px;
    font: bold 2.6em cursive;
    color: #ff0000;
    white-space: nowrap;
    --bg: #fff;
    -webkit-background-clip: text;
    filter: drop-shadow(1px 1px 0px hsla(0, 0%, 0%, .95));
    user-select: none;
    z-index: 1000;
    opacity: .86;
    --motion: cover2;
    --tt: 2s;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    height: 450px;
    overflow: hidden;
}

.lrc::before {
    position: absolute;
    content: attr(data-lrc);
    height: 0%;
    width: 100%;
    color: transparent;
    overflow: hidden;
    white-space: nowrap;
    background: var(--bg);
    filter: inherit;
    -webkit-background-clip: text;
    animation: var(--motion) var(--tt) linear forwards var(--state);
    animation-play-state: var(--state);
}

#vid {
    position: absolute;
    width: 120%;
    height: 120%;
    object-fit: cover;
    top: 0;
    left: 0;
    mix-blend-mode: screen;
    opacity: 0.5;
    pointer-events: none;
    transition: all 10s ease;
    z-index: 1;
}

.raindrop {
    position: absolute;
    top: 0;
    background: linear-gradient(to bottom, transparent, snow);
    transform: translateX(50px);
    animation: drop var(--dur) var(--delay) infinite linear var(--state);
    z-index: 2;
}

@keyframes drop {
    to { top: 100%;
      transform: translateX(-90px);
      }
   }


@keyframes cover1 {
    from { height: 0; }
    to { height: 100%; }
}

@keyframes cover2 {
    from { height: 0; }
    to { height: 100%; }
}


</style>


<div id="mama" class="pa">
    <audio id="aud" src="https://s2.cldisk.com/sv-w7/audio/6c/ef/b8/3cc7d6dbb04f5ea7a2250df7b2667fb2/audio.mp3" crossOrigin="anonymous" ></audio>
<video id="vid" src="https://upfile.mp3.wf/view.php/e166a19fe479d2ecea90af6d076eb665.mp4" autoplay loop muted></video>
<div class="h1">
    ♫ 我等风等雨不等你 ♫</div>

    <div id="lrc" class="lrc" data-lrc="我等风等雨不等你"></div>
   
    <div id="player" class="player">
      <img src="https://pic.imgdb.cn/item/65f0d8669f345e8d03ff5c34.png" alt="播放按钮" style="width:100%;height:100%;">
    </div>
    <div id="prog" class="prog" data-tt="00:00 00:00"></div>
   

    <canvas id="spectrum"></canvas>
</div>

<script>
class Audio {
    constructor(option) {
      this.pa = option.pa;
      this.btn = option.btn;
      this.prog = option.prog;
      this.lrc = option.lrc;
      this.lrcAr = this.parseLRC(option.lrcText);
      this.cssval = '--state';
      this.aud = this.pa.querySelector('audio');
      this.vid = this.pa.querySelector('video');
      this.mKey = 0;
      this.mFlag = true;
      
      // 初始化频谱
      this.initSpectrum();
      
      // 创建雨滴
      this.createRaindrops();
      
      
      this.vid.addEventListener('ended', function() {
            this.currentTime = 0;
            this.play();
      }, false);
      
      this.initVideoEffect();
    }

   
    initSpectrum() {
      this.canvas = document.getElementById('spectrum');
      this.canvasCtx = this.canvas.getContext('2d');
      this.width = this.canvas.width;
      this.height = this.canvas.height;
      
      try {
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            this.audioContext = new AudioContext();
            this.source = this.audioContext.createMediaElementSource(this.aud);
            this.analyser = this.audioContext.createAnalyser();
            
         
            this.analyser.fftSize = 256; // 较小的fftSize会产生较少的频谱线
            this.bufferLength = this.analyser.frequencyBinCount;
            this.dataArray = new Uint8Array(this.bufferLength);
            
            
            this.source.connect(this.analyser);
            this.analyser.connect(this.audioContext.destination);
            
            
            this.drawSpectrum();
      } catch (e) {
            console.error('Web Audio API is not supported in this browser', e);
      }
    }

    // 绘制频谱
    drawSpectrum() {
      if (!this.analyser) return;
      
      requestAnimationFrame(() => this.drawSpectrum());
      
      
      this.canvasCtx.clearRect(0, 0, this.width, this.height);
      
      this.analyser.getByteFrequencyData(this.dataArray);
      
      
      const barWidth = (this.width / this.bufferLength) * 2.5;
      let x = 0;
      
      
      for (let i = 0; i < this.bufferLength; i++) {
         
            const barHeight = (this.dataArray / 255) * this.height * 0.8;
            
         
            const hue =(i / this.bufferLength) * 120; // 0-120 对应红-绿-黄
            this.canvasCtx.fillStyle = `hsl(${hue}, 100%, 0%)`;
            
            this.canvasCtx.fillRect(
                x,
                this.height - barHeight,
                barWidth * 0.8, // 细线条
                barHeight
            );
            
            x += barWidth + 1;
      }
    }

    // 初始化视频特效(独立于音频)
    initVideoEffect() {
      
      const blendModes = [
            'screen', 'overlay', 'soft-light', 'hard-light',
            'multiply', 'difference', 'exclusion', 'hue'
      ];
      
      
      this.applyRandomVideoEffect(blendModes);
      
      
      setInterval(() => {
            this.applyRandomVideoEffect(blendModes);
      }, 12000);
    }
   
    // 应用随机视频特效
    applyRandomVideoEffect(blendModes) {
      // 随机选择一个混合模式
      const randomMode = blendModes;
      
      
      const randomOpacity = (Math.random() * 0.4 + 0.4).toFixed(2);
      
      
      this.vid.style.mixBlendMode = randomMode;
      this.vid.style.opacity = randomOpacity;
    }

    createRaindrops() {
      // 创建100个雨滴元素
      for (let i = 0; i < 100; i++) {
            const raindrop = document.createElement('div');
            raindrop.className = 'raindrop';
            
         
            raindrop.style.cssText = `
                --dur: ${0.4 + Math.random() * 0.4}s;
                --delay: ${Math.random() * -0.8}s;
                width: ${1 + Math.round(Math.random())}px;
                height: ${8 + Math.random() * 15}px;
                left: ${Math.random() * 100}%;
            `;
            
            this.pa.appendChild(raindrop);
      }
    }

    parseLRC(lrcText) {
      const lines = lrcText.split('\n');
      const result = [];
      
      for (const line of lines) {
            if (!line.trim()) continue;
            
            // 匹配时间标签
            const timeMatch = line.match(/^\[(\d+):(\d+)\.(\d+)\]/);
            if (timeMatch) {
                const minutes = parseFloat(timeMatch);
                const seconds = parseFloat(timeMatch);
                const milliseconds = parseFloat(timeMatch) / 100;
                const time = minutes * 60 + seconds + milliseconds;
                const text = line.replace(timeMatch, '').trim();
               
                if (text) {
                  
                  const duration = text.includes(':') || text.includes(':') ? 1.0 : 5.0;
                  result.push();
                }
            }
      }
      
      return result;
    }

    play() {
      let promise = this.aud.play();
      if(promise !== undefined) {
            promise.then(_ => {
                this.mControl();
               
                this.btn.querySelector('img').src = 'https://pic.imgdb.cn/item/65f0d8299f345e8d03ff0b31.gif';
                this.btn.style.opacity = 1;

                if (this.audioContext && this.audioContext.state === 'suspended') {
                  this.audioContext.resume();
                }
            }).catch(error => {
                this.firstPlay();
            });
      }
    }

    firstPlay() {
      let timer = setInterval(() => this.flashElm(this.btn), 500);
      this.btn.onclick = () => {
            this.aud.play().then(_ =>{
                this.mControl();
                this.btn.style.opacity = 0;
                clearInterval(timer);
            
                this.btn.querySelector('img').src = 'https://pic.imgdb.cn/item/65f0d8299f345e8d03ff0b31.gif';
               
               
                if (this.audioContext && this.audioContext.state === 'suspended') {
                  this.audioContext.resume();
                }
            });
      };
    }

    showLrc(time) {
      let name = this.mFlag ? 'cover1' : 'cover2';
      this.lrc.innerHTML = this.lrcAr;
      this.lrc.dataset.lrc = this.lrcAr.replace(/<br>/, '\n');
      this.lrc.style.setProperty('--motion', name);
      this.lrc.style.setProperty('--tt', time + 's');
      this.pa.style.setProperty('--state', 'running');
      this.mKey += 1;
      this.mFlag = !this.mFlag;
    }

    calcKey() {
      for (let j = 0; j < this.lrcAr.length; j++) {
            if (this.aud.currentTime <= this.lrcAr) {
                this.mKey = j - 1;
                break;
            }
      }
      if (this.mKey < 0) this.mKey = 0;
      if (this.mKey > this.lrcAr.length - 1) this.mKey = this.lrcAr.length - 1;
      let time = this.lrcAr - (this.aud.currentTime - this.lrcAr);
      this.showLrc(time);
    }

    mControl() {
      this.btn.onclick = () => {
            if (this.aud.paused) {
                this.aud.play();
               
                this.btn.querySelector('img').src = 'https://pic.imgdb.cn/item/65f0d8299f345e8d03ff0b31.gif';
               
                  
                if (this.audioContext && this.audioContext.state === 'suspended') {
                  this.audioContext.resume();
                }
            } else {
                this.aud.pause();this.btn.style.opacity = 1;
            
                this.btn.querySelector('img').src = 'https://pic.imgdb.cn/item/65f0d8669f345e8d03ff5c34.png';
                     
               
                if (this.audioContext && this.audioContext.state === 'running') {
                  this.audioContext.suspend();
                }
            }
      };

      this.aud.onended = () => {
            this.aud.play();
            this.calcKey();
            
            this.btn.querySelector('img').src = 'https://pic.imgdb.cn/item/65f0d8299f345e8d03ff0b31.gif';
      }

      this.aud.onplaying = () => {
            this.setStyle(this.pa, this.cssval, 'running');
            this.vid.play();
            
         
            this.setStyle(this.pa, '--state', 'running');
      };

      this.aud.onpause = () => {
            this.setStyle(this.pa, this.cssval, 'paused');
            this.vid.pause();
            
         
            this.setStyle(this.pa, '--state', 'paused');
      };

      this.aud.onseeked = () => this.calcKey();

      this.aud.ontimeupdate = () => {
            if(this.prog) {
                let prog = (this.aud.currentTime / this.aud.duration * 100 || 0) + '%';
                this.prog.dataset.tt = this.s2m(this.aud.currentTime) + ' ' + this.s2m(this.aud.duration);
                this.setStyle(this.prog, '--prog', prog);
            }
            if(this.lrc) {
                for (let j = 0; j < this.lrcAr.length; j++) {
                  if (this.aud.currentTime >= this.lrcAr) {
                        if (this.mKey === j) this.showLrc(this.lrcAr);
                        else continue;
                  }
                }
            }
      };

      this.prog.onclick = (e) => this.aud.currentTime = e.offsetX * this.aud.duration / this.prog.offsetWidth;
      this.prog.onmousemove = (e) => this.prog.title = this.s2m(e.offsetX * this.aud.duration / this.prog.offsetWidth);
    }

    setStyle(elm, attribute, val) {
      if(!elm) return;
      elm.style.setProperty(attribute, val);
    }

    flashElm(elm) {
      if(!elm) return;
      elm.style.opacity = Math.random();
    }

    s2m(seconds) {
      if (!seconds) return '00:00';
      let min = parseInt(seconds / 60), sec = parseFloat(Math.floor(seconds) % 60);
      if(min < 10) min = '0' + min;
      if(sec < 10) sec = '0' + sec;
      return min + ':' + sec;
    }
}

const lrcText = `我等风等雨不等你
演唱歌手:烟嗓船长
你锻炼演技我却入了迷
陪你演了一出戏
你真情假意我却爱上你
代价赔上了自己
你说还爱他还是想着他
我就像一个傻瓜
我一心一意不值得一提
谢谢你让我死心
我等风等雨不等你
不再让感情委屈自己
这段情我用尽了力气
既然你退出我何必继续
我碰花蓬草不碰情
不再让自己陷入回忆
这段情最后换来绝情
谢谢你让我学会了放弃
你说还爱他还是想着他
我就像一个傻瓜
我一心一意不值得一提
谢谢你让我死心
我等风等雨不等你
不再让感情委屈自己
这段情我用尽了力气
既然你退出我何必继续
我碰花蓬草不碰情
不再让自己陷入回忆
这段情最后换来绝情
谢谢你让我学会了放弃
`;

var mDatas = {
    pa: document.getElementById('mama'),
    btn: document.getElementById('player'),
    prog: document.getElementById('prog'),
    lrc: document.getElementById('lrc'),
    lrcText: lrcText
};
var audio = new Audio(mDatas);
audio.play();
</script>

梦油 发表于 2025-10-25 10:48

欣赏佳作,问候亚伦。

红影 发表于 2025-10-25 13:54

歌曲里的那个人好悲催,怪不得等风等雨不等对方,应该是已经伤心透顶。
欣赏亚伦老师好帖{:4_199:}

红影 发表于 2025-10-25 13:54

这小频谱真漂亮,小播也好看,真漂亮的制作{:4_199:}
页: [1]
查看完整版本: 我等风等雨不等你