我等风等雨不等你
本帖最后由 亚伦影音工作室 于 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> 欣赏佳作,问候亚伦。 歌曲里的那个人好悲催,怪不得等风等雨不等对方,应该是已经伤心透顶。
欣赏亚伦老师好帖{:4_199:} 这小频谱真漂亮,小播也好看,真漂亮的制作{:4_199:}
页:
[1]