Compare commits

...

5 Commits

5 changed files with 1091 additions and 1510 deletions
File diff suppressed because it is too large Load Diff
-17
View File
@@ -205,17 +205,6 @@
margin: 0 4px;
}
/* 震动效果 */
.shake {
animation: shake 0.15s ease-out;
}
@keyframes shake {
0%, 100% { transform: translate(0, 0); }
25% { transform: translate(-3px, 2px); }
50% { transform: translate(2px, -3px); }
75% { transform: translate(-2px, -1px); }
}
</style>
</head>
<body>
@@ -738,12 +727,6 @@
hue: hue
}));
}
// 屏幕微震
if (bass > 0.5) {
document.body.classList.add('shake');
setTimeout(() => document.body.classList.remove('shake'), 150);
}
}
// 更新和绘制流星
-53
View File
@@ -792,47 +792,8 @@
}
}
// ==================== 扫描环(速度感环) ====================
let rings = [];
function spawnRing() {
rings.push({
radius: 10,
maxRadius: Math.max(width, height) * 0.8,
life: 1,
decay: 0.008,
hue: 200 + Math.random() * 20,
width: 2 + Math.random() * 2
});
}
function updateAndDrawRings(bass) {
for (let i = rings.length - 1; i >= 0; i--) {
const r = rings[i];
r.radius += 8 + bass * 15;
r.life -= r.decay;
if (r.life <= 0 || r.radius > r.maxRadius) {
rings.splice(i, 1);
continue;
}
ctx.save();
ctx.globalAlpha = r.life * 0.3;
ctx.strokeStyle = `hsl(${r.hue}, 15%, 70%)`;
ctx.lineWidth = r.width * r.life;
ctx.shadowBlur = 15;
ctx.shadowColor = 'rgba(255, 255, 255, 0.4)';
ctx.beginPath();
ctx.arc(cx, cy, r.radius, 0, Math.PI * 2);
ctx.stroke();
ctx.restore();
}
}
// ==================== 主渲染循环 ====================
let lastTime = 0;
let ringTimer = 0;
let warpLineTimer = 0;
let speedValue = 0;
@@ -899,20 +860,6 @@
}
updateAndDrawWarpLines(bass, treble);
// 生成和绘制扫描环(无声音时不生成)
if (avg > 0.03) {
ringTimer += dt;
const ringInterval = Math.max(200, 800 - avg * 500 - bass * 300);
if (ringTimer > ringInterval) {
ringTimer = 0;
spawnRing();
}
if (isBeat && bass > 0.4) {
spawnRing();
}
}
updateAndDrawRings(bass);
// 节拍粒子爆发
if (isBeat && bass > 0.3) {
spawnParticles(0.5 + bass);
File diff suppressed because it is too large Load Diff
+111
View File
@@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音频可视化</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
background: #111;
overflow: hidden;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 4px;
width: 100vw;
height: 100vh;
background: #000;
}
.cell {
position: relative;
background: #111;
overflow: hidden;
}
.cell iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}
.cell select {
position: absolute;
top: 8px;
left: 8px;
z-index: 10;
background: rgba(0, 0, 0, 0.6);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
padding: 2px 6px;
font-size: 12px;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
}
.cell:hover select {
opacity: 1;
visibility: visible;
}
</style>
</head>
<body>
<div class="grid" id="grid"></div>
<script>
// 可供选择的页面列表
const pages = [
'1.html', '2.html', '3.html', '4.html',
'5.html', '6.html', '7.html', '8.html',
];
// 4 个格子默认显示的页面
const defaults = ['2.html', '6.html', '7.html', '8.html'];
const grid = document.getElementById('grid');
defaults.forEach((current) => {
const cell = document.createElement('div');
cell.className = 'cell';
const iframe = document.createElement('iframe');
iframe.src = current;
const select = document.createElement('select');
pages.forEach((p) => {
const opt = document.createElement('option');
opt.value = p;
opt.textContent = p;
if (p === current) opt.selected = true;
select.appendChild(opt);
});
// 切换时更新对应 iframe
select.addEventListener('change', () => { iframe.src = select.value; });
cell.appendChild(select);
cell.appendChild(iframe);
grid.appendChild(cell);
});
</script>
</body>
</html>