感觉往上没有几个自己喜欢的ICP备案页
就自己写了一个出来,如果有需要改进的地方还请各位大佬提一下意见
很多地方都加了备注需要的可以自行修改一下
效果网站:小鎻的备案页
<!doctype html><html lang="zh-CN"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> <title>ICP备案页</title> <!-- ✅ 外链 CSS:避免 CSP 禁止 <style> 或 unsafe-inline --><style>:root{ --bg-fade:.12; --grad-speed:4s; --text:#081018;}*{box-sizing:border-box}html,body{ margin:0;height:100%;overflow:hidden;background:#f5f8ff;color:var(--text); font-family:system-ui,-apple-system,"Segoe UI",Roboto,Arial,"PingFang SC","Microsoft YaHei",sans-serif; -webkit-font-smoothing:antialiased;}#bg{position:fixed;inset:0;width:100%;height:100%;z-index:0;touch-action:none}#content{ position:relative;z-index:1;height:100%;width:100%; display:flex;flex-direction:column;align-items:center;justify-content:center; text-align:center;pointer-events:none; padding:min(8vh,56px) min(6vw,40px);}/* 信息卡片:重新排版 */#content::before{content:none; display:none;}/* 重新排版的间距容器 */#content{gap:clamp(8px,1.6vh,14px)}.neon{ --h1:180;--h2:210;--h3:240;--gh:205; --l1:18%;--l2:22%;--l3:18%;--gl:20%; --s1:95%;--s2:95%;--s3:95%; background:linear-gradient(90deg, hsl(var(--h1) var(--s1) var(--l1)), hsl(var(--h2) var(--s2) var(--l2)), hsl(var(--h3) var(--s3) var(--l3))); background-size:300% 300%; background-position:0% 50%; -webkit-background-clip:text;background-clip:text;color:transparent; text-shadow: 0 0 2px hsla(var(--gh),80%,18%,.55), 0 0 6px hsla(var(--gh),80%,18%,.35), 0 0 12px hsla(var(--gh),80%,18%,.18); margin:0;line-height:1.2;word-break:break-all; transition:filter .12s,transform .12s,opacity .12s; will-change:filter,transform,opacity,background-position,text-shadow; animation:gradShift var(--grad-speed) ease-in-out infinite;}@keyframes gradShift{ 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%}}#company{font-size:clamp(30px,7vw,86px);font-weight:950;letter-spacing:clamp(.8px,.35vw,3.5px);margin-bottom:clamp(4px,1vh,10px)}#icp,#contact{font-size:clamp(15px,3vw,28px);font-weight:700;letter-spacing:.06em}#policeIcon{margin-right:.3em;filter:drop-shadow(0 0 3px rgba(0,0,0,.35))}.mail{color:inherit;text-decoration:none;pointer-events:none;cursor:default}.off{opacity:.55}#glow{ position:fixed;top:0;left:0;z-index:2;pointer-events:none;border-radius:50%; width:clamp(120px,18vw,220px);height:clamp(120px,18vw,220px); margin-left:calc(clamp(120px,18vw,220px)/-2); margin-top:calc(clamp(120px,18vw,220px)/-2); background:radial-gradient(circle,rgba(0,0,0,.05) 0%,rgba(0,0,0,0) 70%); mix-blend-mode:multiply;filter:blur(1px);transform:translate(-9999px,-9999px);}#coreValuesLayer{ position: fixed; inset: 0; z-index: 4; pointer-events: none; overflow: hidden;}.core-value{ position:absolute;font-weight:1000;font-size:clamp(20px,4vw,46px); color: hsl(var(--h) 90% 18%); /* ✅ 不支持渐变裁剪时的随机深色兜底 */ background: linear-gradient(90deg, hsl(var(--h),100%,22%), hsl(calc(var(--h) + 35),100%,16%), hsl(calc(var(--h) + 70),100%,20%)); -webkit-background-clip:text;background-clip:text;color:transparent; background-size: 220% 220%; animation: corePop 1500ms ease-out forwards, coreGradShift 900ms ease-in-out infinite; text-shadow:0 0 1px hsla(var(--h),80%,30%,.85),0 0 6px rgba(0,0,0,.45); transform: translate(-50%, -50%) scale(.6) rotate(var(--rot)); opacity:0;white-space:nowrap;letter-spacing:.1em;}@keyframes corePop{ 0%{opacity:0;transform:translate(-50%,-50%) scale(.55) rotate(var(--rot));filter:blur(2px)}@keyframes coreGradShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}} 15%{opacity:1;transform:translate(-50%,-50%) scale(1.05) rotate(var(--rot));filter:blur(0)} 100%{opacity:0;transform:translate(-50%,-50%) scale(1.25) rotate(var(--rot)) translateY(-40px)}}#prompt{ position:fixed;inset:0;z-index:3;display:flex;align-items:center;justify-content:center; background:rgba(255,255,255,.85);color:#000;text-align:center;cursor:pointer;user-select:none; font-size:clamp(16px,4vw,24px);line-height:1.6;text-shadow:none;padding:24px; border-top:1px solid rgba(0,0,0,.08); backdrop-filter: blur(6px);}#prompt .hint{opacity:.8;font-size:.85em;margin-top:.6em}#promptSkip{ margin-top:14px;padding:8px 14px;border-radius:999px;border:1px solid rgba(0,0,0,.25); background:rgba(0,0,0,.06);color:#000;cursor:pointer;font-size:.9em;pointer-events:auto;}@media (max-width:360px){ #company{font-size:clamp(22px,7vw,40px)} #content{gap:6px}}/* 点击渐变波纹 */#clickRippleLayer{ position:fixed; inset:0; z-index:4; pointer-events:none; overflow:hidden;}.click-ripple{ position:absolute; width: 24px; height: 24px; border-radius:50%; transform: translate(-50%,-50%) scale(0); opacity: .9; background: radial-gradient(circle, hsla(var(--rh),100%,35%,0.9) 0%, hsla(calc(var(--rh) + 60),100%,30%,0.6) 35%, hsla(calc(var(--rh) + 120),100%,28%,0.15) 60%, rgba(0,0,0,0) 70%); mix-blend-mode:multiply; animation: rippleOut 900ms ease-out forwards; filter: blur(0.2px);}@keyframes rippleOut{ 0%{transform:translate(-50%,-50%) scale(0); opacity:.9;} 60%{transform:translate(-50%,-50%) scale(8); opacity:.55;} 100%{transform:translate(-50%,-50%) scale(12); opacity:0;}}#divider{ position: relative; width: clamp(140px, 28vw, 260px); height: 7px; margin: clamp(6px, 1.6vh, 10px) 0 clamp(8px, 1.8vh, 14px); opacity:.98; background: transparent; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.12)); /* 渐变控制变量(JS 会根据节拍实时改) */ --dh1: 200; --dh2: 260; --dh3: 320; --dl1: 20%; --dl2: 16%; --dl3: 22%; --ds: 95%;}/* 中间主线:三段渐变霓虹 */#divider::before{ content:""; position:absolute;left:0;right:0;top:50%; height:2px;transform:translateY(-50%); background: linear-gradient(90deg, hsla(var(--dh1), var(--ds), var(--dl1), 0) 0%, hsla(var(--dh1), var(--ds), var(--dl1), .9) 18%, hsla(var(--dh2), var(--ds), var(--dl2), .95) 50%, hsla(var(--dh3), var(--ds), var(--dl3), .9) 82%, hsla(var(--dh3), var(--ds), var(--dl3), 0) 100%); border-radius:999px; box-shadow: 0 0 8px hsla(var(--dh2), var(--ds), 35%, .25);}/* 节点:同款渐变点阵 */#divider::after{ content:""; position:absolute;left:50%;top:50%; width:68%;height:100%; transform:translate(-50%,-50%); background: radial-gradient(circle at 0% 50%, hsla(var(--dh1), var(--ds), var(--dl1), 1) 0 2.2px, transparent 2.8px), radial-gradient(circle at 100% 50%, hsla(var(--dh3), var(--ds), var(--dl3), 1) 0 2.2px, transparent 2.8px), radial-gradient(circle at 36% 50%, hsla(var(--dh2), var(--ds), var(--dl2), .9) 0 1.6px, transparent 2.2px), radial-gradient(circle at 64% 50%, hsla(var(--dh2), var(--ds), var(--dl2), .9) 0 1.6px, transparent 2.2px); opacity:.95;}/* 扫描高光:渐变色随节拍走 */#divider .scan{ position:absolute;inset:0;border-radius:999px;overflow:hidden;background:transparent;}#divider .scan::before{ content:""; position:absolute;top:50%;left:-35%; width:28%;height:2px;transform:translateY(-50%); background:linear-gradient(90deg, hsla(var(--dh1), var(--ds), 40%, 0), hsla(var(--dh2), var(--ds), 40%, .95), hsla(var(--dh3), var(--ds), 40%, 0)); filter: blur(0.2px); animation: dividerScan 2.4s ease-in-out infinite;}@keyframes dividerScan{ 0%{left:-35%;opacity:0;} 18%{opacity:.75;} 50%{left:100%;opacity:.9;} 100%{left:135%;opacity:0;}} 18%{opacity:.7;} 50%{left:100%;opacity:.85;} 100%{left:135%;opacity:0;}} 15%{opacity:.8;} 50%{left:100%;opacity:.9;} 100%{left:130%;opacity:0;}}</style></head><body> <canvas id="bg"></canvas> <main id="content"> <h1 id="company" class="neon">页面介绍xxxxxx</h1> <div id="divider" aria-hidden="true"><span class="scan"></span></div> <p id="icp" class="neon">ICP备案号 · xxxxxxxxxxx</p><p id="contact" class="neon">联系邮箱 · <span class="mail">[email protected]</span> </p> </main> <div id="glow"></div> <div id="coreValuesLayer"></div> <!-- 点击渐变波纹层 --> <div id="clickRippleLayer"></div> <div id="prompt"> <div> <div id="promptTitle">点击/轻触页面以启用音乐与全部动态特效</div> <div id="promptStatus" class="hint">(手机浏览器必须先轻触一次才会播放音乐)</div> <div class="hint" style="margin-top:8px;">如果音乐加载失败,特效仍可运行。</div> <button id="promptSkip" type="button">跳过音乐,直接进入</button> <div class="hint" style="margin-top:8px;">若一直卡在此层:说明 JS 被安全策略拦截,请看控制台报错。</div> </div> </div> <!-- ✅ 外链 JS:避免 CSP 禁止内联 <script> --><script>(() => { const $ = s => document.querySelector(s); const canvas = $('#bg'), ctx = canvas.getContext('2d'); const glow = $('#glow'), prompt = $('#prompt'); const promptStatus = $('#promptStatus'), promptSkip = $('#promptSkip'); const neonEls = [...document.querySelectorAll('.neon')]; // ===== 配置 ===== const CFG = { pcBase:120, pcMin:60, pcMax:240, barsBase:96, barsMin:48, barsMax:160, link:150, spectrumRatio:.33, scanSpeed:1.6, beamSpeed:2.2, diagSpeed:1.1, glowPulse:.015, hueDrift:.35 }; let W=0,H=0,dpr=1,particles=[],scanY=0,beamX=0,diagT=0,flick=0,hue=180; let colorTimer=0, colorInterval=1200; let flickerTimer=0, flickerInterval=180; let flickerMul=1, targetFlickerMul=1; const lerp=(a,b,t)=>a+(b-a)*t; const clamp=(v,a,b)=>Math.min(b,Math.max(a,v)); const avg=(arr,n)=>{let s=0; for(let i=0;i<n;i++) s+=arr[i]||0; return s/n;}; const avgFrom=(arr,start)=>{let s=0,c=0; for(let i=start;i<arr.length;i++){s+=arr[i]||0;c++;} return c?s/c:0;}; function initParticles(){ particles = Array.from({length:CFG.pc}, () => ({ x:Math.random()*W, y:Math.random()*H, vx:(Math.random()-.5)*.8, vy:(Math.random()-.5)*.8, r:1.2+Math.random()*2.4, ho:Math.random()*360 })); } // ===== 漂落彩色树叶(常驻背景)===== const FLAKE_COUNT = 120; // 雪花数量(全端适配,已算保守) const FLAKE_COLORS = [ "hsla(0,90%,60%,0.9)", "hsla(30,90%,60%,0.9)", "hsla(60,90%,60%,0.9)", "hsla(120,90%,60%,0.9)", "hsla(180,90%,60%,0.9)","hsla(220,90%,60%,0.9)", "hsla(280,90%,60%,0.9)", "hsla(320,90%,60%,0.9)" ]; let flakes = []; function initFlakes(){ flakes = Array.from({length: Math.round(FLAKE_COUNT * (innerWidth/1280*0.7 + 0.6))}, () => ({ x: Math.random()*W, y: Math.random()*H, r: 2 + Math.random()*5, vy: 0.6 + Math.random()*1.6, vx: (Math.random()-0.5)*0.6, wobble: Math.random()*Math.PI*2, wobbleSpeed: 0.01 + Math.random()*0.03, rot: Math.random()*Math.PI*2, rotSpeed: (Math.random()-0.5)*0.02, color: FLAKE_COLORS[(Math.random()*FLAKE_COLORS.length)|0], shape: "leaf" })); } function resize(){ dpr = Math.max(1, devicePixelRatio||1); W = innerWidth; H = innerHeight; canvas.width = (W*dpr)|0; canvas.height = (H*dpr)|0; canvas.style.width=W+'px'; canvas.style.height=H+'px'; ctx.setTransform(dpr,0,0,dpr,0,0); const area=W*H; CFG.pc = clamp(Math.round(CFG.pcBase*area/(1280*720)), CFG.pcMin, CFG.pcMax); CFG.bars = clamp(Math.round(CFG.barsBase*W/1280), CFG.barsMin, CFG.barsMax); CFG.link = Math.min(W,H)*.22 + 70; initParticles(); initFlakes(); } // ===== 音频(本地路径)===== let AC=null, analyser=null, freq=new Uint8Array(256), time=new Uint8Array(256), audio=null; const AUDIO_URL = "./nginx/1.mp3"; function initAudio(){ if (AC) return; const Ctx = window.AudioContext||window.webkitAudioContext; AC = new Ctx(); audio = new Audio(AUDIO_URL); audio.loop = true; audio.preload = "auto"; audio.crossOrigin = "anonymous"; // ✅ 移动端关键:允许在页面内播放,不强制全屏 audio.playsInline = true; audio.setAttribute('playsinline',''); audio.setAttribute('webkit-playsinline',''); audio.muted = false; audio.addEventListener('error', () => { promptStatus && (promptStatus.textContent="音乐加载失败(路径/权限/格式问题),已跳过音乐"); console.warn("Audio load error:", AUDIO_URL); }); const src = AC.createMediaElementSource(audio); analyser = AC.createAnalyser(); analyser.fftSize=512; src.connect(analyser); analyser.connect(AC.destination); freq = new Uint8Array(analyser.frequencyBinCount); time = new Uint8Array(analyser.frequencyBinCount); } async function unlock(){ // ✅ 先无条件隐藏提示,避免“卡层” if (prompt) prompt.style.display='none'; removeEventListener('pointerdown', unlock); removeEventListener('mousedown', unlock); removeEventListener('touchstart', unlock); removeEventListener('keydown', unlock); prompt && prompt.removeEventListener('click', unlock); try{ initAudio(); if (AC && AC.state==='suspended') await AC.resume(); if (audio){ try{ audio.currentTime = 0; }catch(e){} const p = audio.play(); if (p && p.then) await p; } }catch(e){ console.warn("Unlock/play failed:", e); promptStatus && (promptStatus.textContent="浏览器阻止播放,特效已启动(再点一次可播)"); if(prompt){ prompt.style.display='flex'; prompt.addEventListener('click', async () => { try{ if(!AC) initAudio(); if(AC.state==='suspended') await AC.resume(); await audio.play(); prompt.style.display='none'; }catch(err){ console.warn(err); } }, {once:true}); } } } addEventListener('pointerdown', unlock, {once:true}); addEventListener('mousedown', unlock, {once:true}); addEventListener('touchstart', unlock, {once:true, passive:true}); addEventListener('touchend', unlock, {once:true, passive:true}); // ✅ iOS 兜底 addEventListener('keydown', unlock, {once:true}); prompt && prompt.addEventListener('click', unlock); promptSkip && promptSkip.addEventListener('click', (e)=>{ e.stopPropagation(); prompt.style.display='none';}); // ===== 点击出现核心价值观,每次3条 ===== const coreLayer = $('#coreValuesLayer'); const CORE_VALUES = ["富强","民主","文明","和谐","自由","平等","公正","法治","爱国","敬业","诚信","友善"]; const DECOR_LEFT = ["✨","🌟","⚡","🫧","🔷","💠","☄️","🎇","🌀","🧿","❖","▣","✦","✧","🪩"]; // ===== 点击渐变波纹(跟随鼠标点击)===== const rippleLayer = document.querySelector('#clickRippleLayer'); function spawnRipple(x,y,hue){ if(!rippleLayer) return; const r=document.createElement('div'); r.className='click-ripple'; r.style.left=x+'px'; r.style.top=y+'px'; r.style.setProperty('--rh', hue ?? ((Math.random()*360)|0)); rippleLayer.appendChild(r); r.addEventListener('animationend',()=>r.remove()); } const DECOR_RIGHT = ["✨","🌟","⚡","🔥","🎆","🌈","🫶","🎧","🚀","🛸","✺","✹","✸","❖","★"]; function sample3(arr){ const a=arr.slice(); for(let i=a.length-1;i>0;i--){const j=(Math.random()*(i+1))|0;[a[i],a[j]]=[a[j],a[i]];} return a.slice(0,3); } function spawnCoreValues(x,y){ if(!coreLayer) return; const radius=Math.min(innerWidth,innerHeight)*0.07; // ✅ 半径缩小:更靠近鼠标 sample3(CORE_VALUES).forEach((val,i)=>{ const el=document.createElement('div'); el.className='core-value'; el.textContent=`${DECOR_LEFT[(Math.random()*DECOR_LEFT.length)|0]} ${val} ${DECOR_RIGHT[(Math.random()*DECOR_RIGHT.length)|0]}`; const ang=(i/3)*Math.PI*2-Math.PI/2; const r=radius*(0.45+Math.random()*0.55); // ✅ 更集中 el.style.left=(x+Math.cos(ang)*r+(Math.random()-0.5)*8)+'px'; el.style.top =(y+Math.sin(ang)*r+(Math.random()-0.5)*8)+'px'; el.style.setProperty('--rot',((Math.random()-0.5)*16).toFixed(1)+'deg'); el.style.setProperty('--h',((Math.random()*360)|0)); coreLayer.appendChild(el); el.addEventListener('animationend',()=>el.remove()); }); } addEventListener('pointerdown',(e)=>{ const t=e.target; if(t && (t.id==='promptSkip' || t.closest('#prompt'))) return; spawnRipple(e.clientX, e.clientY, (Math.random()*360)|0); spawnCoreValues(e.clientX,e.clientY); },{passive:true}); function drawLeaf(f){ ctx.save(); ctx.translate(f.x, f.y); ctx.rotate(f.rot); ctx.fillStyle = f.color; ctx.globalAlpha = 0.85; const s = f.r*1.6; ctx.beginPath(); // 叶片(椭圆+尖) ctx.moveTo(0, -s); ctx.quadraticCurveTo(s*0.9, -s*0.2, 0, s); ctx.quadraticCurveTo(-s*0.9, -s*0.2, 0, -s); ctx.fill(); // 叶脉 ctx.strokeStyle="rgba(0,0,0,0.15)"; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(0,-s*0.9); ctx.lineTo(0,s*0.8); ctx.stroke(); ctx.restore(); } // ===== 主循环 ===== function tick(now){ const bgFade = 0.12; ctx.fillStyle = `rgba(245,248,255,${bgFade})`; ctx.fillRect(0,0,W,H); // ===== 彩色树叶下落层 ===== for(const f of flakes){ f.wobble += f.wobbleSpeed; f.x += Math.sin(f.wobble)*0.6 + f.vx; f.y += f.vy; f.rot += f.rotSpeed; // 出屏重生 if(f.y - f.r > H){ f.y = -10 - Math.random()*H*0.1; f.x = Math.random()*W; f.vy = 0.6 + Math.random()*1.8; f.vx = (Math.random()-0.5)*0.6; f.r = 2 + Math.random()*5; f.color = FLAKE_COLORS[(Math.random()*FLAKE_COLORS.length)|0]; f.shape = "leaf"; } if(f.x < -20) f.x = W+20; if(f.x > W+20) f.x = -20; drawLeaf(f); } if (analyser){ analyser.getByteFrequencyData(freq); analyser.getByteTimeDomainData(time); } const avgAmp = avg(freq, freq.length); const bass = avg(freq, Math.min(8,freq.length)); const treble = avgFrom(freq, Math.min(80,freq.length-1)); // ===== 分隔线渐变随音乐变色 ===== const divider = document.querySelector('#divider'); if (divider){ // 以当前背景主色(hue)为基,按节拍抖动/旋转色相 const kick = bass/255; // 0~1 const energy = avgAmp/255; // 0~1 const baseH = (hue + 140 + kick*80) % 360; // 互补偏移,让对比更强 const h1 = (baseH + 0) % 360; const h2 = (baseH + 40 + energy*60) % 360; const h3 = (baseH + 80 + kick*120) % 360; divider.style.setProperty('--dh1', h1.toFixed(1)); divider.style.setProperty('--dh2', h2.toFixed(1)); divider.style.setProperty('--dh3', h3.toFixed(1)); // 亮度也跟节奏走:强拍更亮 divider.style.setProperty('--dl1', (14 + kick*18).toFixed(1) + '%'); divider.style.setProperty('--dl2', (12 + energy*16).toFixed(1) + '%'); divider.style.setProperty('--dl3', (15 + kick*20).toFixed(1) + '%'); divider.style.setProperty('--ds', (90 + kick*20).toFixed(0) + '%'); } // 背景浅、文字深:锁定高对比 const bgL = clamp(82 + avgAmp/40, 78, 92); const textL = clamp(18 - avgAmp/180, 8, 22); const textGlowL = clamp(textL + 6, 12, 28); const bgS = clamp(35 + treble/8, 30, 55); const textS = clamp(85 + bass/6, 80, 100); hue = (hue + CFG.hueDrift + avgAmp/140) % 360; const speed = .5 + avgAmp/255; // 渐变更新 if (now - colorTimer > colorInterval){ colorTimer=now; const base=(hue+160+Math.random()*80)%360; neonEls.forEach(el=>{ const h1=(base+Math.random()*60)%360; const h2=(h1+30+Math.random()*50)%360; const h3=(h2+30+Math.random()*50)%360; const gh=(h2+5)%360; el.style.setProperty('--h1',h1.toFixed(1)); el.style.setProperty('--h2',h2.toFixed(1)); el.style.setProperty('--h3',h3.toFixed(1)); el.style.setProperty('--gh',gh.toFixed(1)); el.style.setProperty('--l1',textL.toFixed(1)+'%'); el.style.setProperty('--l2',clamp(textL+6,6,30).toFixed(1)+'%'); el.style.setProperty('--l3',textL.toFixed(1)+'%'); el.style.setProperty('--gl',textGlowL.toFixed(1)+'%'); el.style.setProperty('--s1',textS.toFixed(0)+'%'); el.style.setProperty('--s2',textS.toFixed(0)+'%'); el.style.setProperty('--s3',textS.toFixed(0)+'%'); }); } // 轻微闪烁 flickerMul = lerp(flickerMul, targetFlickerMul, 0.12); if (now - flickerTimer > flickerInterval){ flickerTimer=now; const kick=bass/255; targetFlickerMul=0.92+Math.random()*0.18+kick*0.15; } // 粒子 for (const p of particles){ p.x += p.vx*speed; p.y += p.vy*speed; if (p.x<0) p.x+=W; else if (p.x>W) p.x-=W; if (p.y<0) p.y+=H; else if (p.y>H) p.y-=H; const ph=(hue+p.ho)%360; ctx.beginPath(); ctx.fillStyle=`hsla(${ph},${bgS}%,${bgL}%,.35)`; ctx.shadowBlur=8+bass/12; ctx.shadowColor=`hsla(${ph},80%,${clamp(bgL-20,25,70)}%,.4)`; ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.fill(); } // 连线 ctx.save(); ctx.shadowBlur=0; const md=CFG.link, md2=md*md; for(let i=0;i<particles.length;i++) for(let j=i+1;j<particles.length;j++){ const a=particles[i], b=particles[j]; const dx=a.x-b.x, dy=a.y-b.y, d2=dx*dx+dy*dy; if(d2<md2){ const d=Math.sqrt(d2); const alpha=(1-d/md)*.2*(.5+treble/255); ctx.strokeStyle=`hsla(${(hue+40)%360},${bgS}%,${clamp(bgL-5,30,80)}%,${alpha})`; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke(); } } ctx.restore(); // 频谱柱 const bars=CFG.bars, barW=W/bars, maxH=H*CFG.spectrumRatio; ctx.save(); ctx.shadowBlur=10; for(let i=0;i<bars;i++){ const v=freq[i]||0, bh=v/255*maxH; const x=i*barW, y=H-bh, h2=(hue+i*1.8)%360; ctx.fillStyle=`hsla(${h2},${bgS}%,${clamp(bgL-10,30,80)}%,.45)`; ctx.fillRect(x+barW*.18, y, barW*.64, bh); } ctx.restore(); // 波形 const waveY=H*.70, n=time.length; ctx.save(); ctx.lineWidth=2; ctx.shadowBlur=8; ctx.shadowColor=`hsla(${(hue+180)%360},${bgS}%,${clamp(bgL-15,30,75)}%,.8)`; ctx.strokeStyle=`hsla(${(hue+180)%360},${bgS}%,${clamp(bgL-15,30,75)}%,.65)`; ctx.beginPath(); for(let i=0;i<n;i++){ const vv=(time[i]-128)/128; const x=i/(n-1)*W; const y=waveY+vv*(18+bass/4); i? ctx.lineTo(x,y):ctx.moveTo(x,y); } ctx.stroke(); ctx.restore(); // 文字呼吸 const breathe=1+Math.sin(now*CFG.glowPulse)*.12; const boost=clamp(.9+avgAmp/300,.9,1.4)*flickerMul; const scale=clamp(1+bass/1600,1,1.04); neonEls.forEach(el=>{ el.style.filter=`brightness(${breathe*boost}) saturate(${1.1+treble/500})`; el.style.transform=`scale(${scale})`; }); requestAnimationFrame(tick); } const moveGlow=(x,y)=>glow && (glow.style.transform=`translate(${x}px,${y}px)`); addEventListener('pointermove', e=>moveGlow(e.clientX,e.clientY), {passive:true}); addEventListener('pointerdown', e=>moveGlow(e.clientX,e.clientY), {passive:true}); addEventListener('resize', resize); resize(); requestAnimationFrame(tick);})();</script></body></html>
评论 (0)