// ==UserScript== // @name 彩虹 // @namespace http://tampermonkey.net/ // @version 1.4 // @description 雨 → 彩虹 // @author YourName // @match *://*/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; if (window.top !== window.self) return; let animFrame = null; let canvas = null; let resizeTimer = null; function stopAnimation() { if (animFrame) { cancelAnimationFrame(animFrame); animFrame = null; } } function removeCanvas() { if (canvas && canvas.parentNode) { canvas.parentNode.removeChild(canvas); canvas = null; } } function resizeCanvas() { if (!canvas) return; canvas.width = window.innerWidth; canvas.height = window.innerHeight; } // ---------- 向下拱形彩虹(连续实线 + 阴影,从左到右渐显) ---------- function startRainbow(durationSec = 1.5) { if (!canvas) return; const ctx = canvas.getContext('2d'); const w = canvas.width; const h = canvas.height; stopAnimation(); // 彩虹参数:向下拱形,圆心位于屏幕中部偏下 const centerX = w / 2; const centerY = h * 0.6; const outerRadius = Math.min(w, h) * 0.35; const innerRadius = Math.min(w, h) * 0.15; const bandCount = 7; const bandWidth = (outerRadius - innerRadius) / bandCount; // 颜色顺序:红在外圈(最下),紫在内圈(最上) const colors = ['#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#4B0082', '#8F00FF']; // 移除虚线,使用实线;设置阴影 ctx.lineWidth = bandWidth; ctx.lineCap = 'butt'; ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; ctx.shadowBlur = 6; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; const startTime = performance.now(); const duration = durationSec * 1000; function drawFrame(now) { const elapsed = now - startTime; const progress = Math.min(elapsed / duration, 1); ctx.clearRect(0, 0, w, h); ctx.save(); ctx.beginPath(); ctx.rect(0, 0, progress * w, h); ctx.clip(); // 绘制下半圆 (从 PI 到 2*PI) for (let i = 0; i < bandCount; i++) { const radius = outerRadius - i * bandWidth - bandWidth / 2; ctx.beginPath(); ctx.arc(centerX, centerY, radius, Math.PI, 2 * Math.PI, false); ctx.strokeStyle = colors[i]; ctx.stroke(); } ctx.restore(); if (progress < 1) { animFrame = requestAnimationFrame(drawFrame); } else { // 停留3秒后清除 setTimeout(() => { removeCanvas(); }, 3000); animFrame = null; } } animFrame = requestAnimationFrame(drawFrame); } // ---------- 下雨动画(蓝色大颗粒,与之前相同) ---------- function startRain(durationSec = 3) { stopAnimation(); removeCanvas(); canvas = document.createElement('canvas'); canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.width = '100%'; canvas.style.height = '100%'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '9999'; canvas.style.imageRendering = 'pixelated'; canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); const ctx = canvas.getContext('2d'); const w = canvas.width; const h = canvas.height; const dropCount = 150; const drops = []; for (let i = 0; i < dropCount; i++) { drops.push({ x: Math.random() * w, y: Math.random() * h, speed: 3 + Math.random() * 8, len: 4 + Math.floor(Math.random() * 5) // 长度 4~8 像素 }); } const startTime = performance.now(); const duration = durationSec * 1000; function drawRain(now) { if (canvas.width !== window.innerWidth || canvas.height !== window.innerHeight) { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#00a5ff'; for (let drop of drops) { drop.y += drop.speed; if (drop.y > canvas.height) { drop.y = 0; drop.x = Math.random() * canvas.width; } ctx.fillRect(drop.x, drop.y, 4, drop.len); } if (now - startTime < duration) { animFrame = requestAnimationFrame(drawRain); } else { startRainbow(1.5); } } animFrame = requestAnimationFrame(drawRain); } // ---------- 控制面板(不变) ---------- function createControlPanel() { const panel = document.createElement('div'); panel.id = 'pixel-rain-panel'; panel.innerHTML = `
🌈 控制台
蓝色像素雨 → 下拱彩虹(连续实线+阴影)
`; panel.style.position = 'fixed'; panel.style.top = '20px'; panel.style.right = '20px'; panel.style.zIndex = '10001'; panel.style.userSelect = 'none'; document.body.appendChild(panel); document.getElementById('start-effect').addEventListener('click', () => { const duration = parseFloat(document.getElementById('rain-duration').value); if (isNaN(duration) || duration <= 0) { alert('请输入大于0的数字'); return; } startRain(duration); }); document.getElementById('close-panel').addEventListener('click', () => { panel.style.display = 'none'; }); document.addEventListener('dblclick', (e) => { if (!panel.contains(e.target)) { panel.style.display = 'block'; } }); } window.addEventListener('resize', () => { if (canvas) { if (resizeTimer) clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { if (canvas) { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } }, 100); } }); createControlPanel(); })();