// ==UserScript==
// @name 网页趣味特效大师 ✨
// @namespace http://tampermonkey.net/
// @version 1.0001
// @description 为你的网页浏览增添趣味!包含鼠标粒子特效、彩虹轨迹、元素弹跳动画和星星飘落效果,让上网变得更有趣!
// @author 半竹
// @match *://*/*
// @grant none
// @license MIT
// @icon data:image/svg+xml,
// ==/UserScript==
(function() {
'use strict';
// ============================================
// 🎉 网页趣味特效大师 - 让浏览更有趣!
// ============================================
const CONFIG = {
particleCount: 12, // 点击产生的粒子数量
trailLength: 20, // 鼠标轨迹长度
starCount: 15, // 同时显示的星星数量
floatCount: 8, // 漂浮表情数量
loadEffect: true, // 是否启用页面加载特效
timeDisplay: true, // 是否显示时间
weatherEffect: true, // 是否启用天气效果
soundEffect: true, // 是否启用音效
dynamicBackground: true, // 是否启用动态背景
hoverEffect: true, // 是否启用鼠标悬停特效
keyboardEffect: true, // 是否启用键盘特效
themeToggle: true, // 是否启用主题切换
enableParticles: true, // 是否启用粒子效果
enableTrail: true, // 是否启用彩虹轨迹
enableBounce: true, // 是否启用弹跳效果
enableStars: true, // 是否启用星星效果
enableFloat: true, // 是否启用漂浮表情
enableScroll: true // 是否启用滚动特效
};
// 创建特效容器
const container = document.createElement('div');
container.id = 'fun-effects-container';
container.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999999;
overflow: hidden;
`;
document.body.appendChild(container);
// ============================================
// 🎨 工具函数
// ============================================
// 随机颜色生成器
function getRandomColor() {
const hue = Math.random() * 360;
return `hsl(${hue}, 70%, 60%)`;
}
// 随机数生成器
function random(min, max) {
return Math.random() * (max - min) + min;
}
// ============================================
// 💥 点击粒子爆炸效果
// ============================================
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = random(5, 12);
this.speedX = random(-8, 8);
this.speedY = random(-8, 8);
this.color = getRandomColor();
this.life = 1;
this.decay = random(0.015, 0.03);
this.gravity = 0.2;
this.element = document.createElement('div');
this.element.style.cssText = `
position: absolute;
width: ${this.size}px;
height: ${this.size}px;
background: ${this.color};
border-radius: 50%;
pointer-events: none;
box-shadow: 0 0 10px ${this.color};
`;
container.appendChild(this.element);
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += this.gravity;
this.life -= this.decay;
this.size *= 0.98;
this.element.style.left = this.x + 'px';
this.element.style.top = this.y + 'px';
this.element.style.transform = `scale(${this.life})`;
this.element.style.opacity = this.life;
return this.life > 0;
}
destroy() {
this.element.remove();
}
}
let particles = [];
function createExplosion(x, y) {
if (!CONFIG.enableParticles) return;
for (let i = 0; i < CONFIG.particleCount; i++) {
particles.push(new Particle(x, y));
}
}
// ============================================
// 🌈 鼠标彩虹轨迹
// ============================================
class TrailDot {
constructor(x, y, hue) {
this.x = x;
this.y = y;
this.hue = hue;
this.life = 1;
this.element = document.createElement('div');
this.element.style.cssText = `
position: absolute;
width: 8px;
height: 8px;
background: hsl(${hue}, 80%, 60%);
border-radius: 50%;
pointer-events: none;
box-shadow: 0 0 15px hsl(${hue}, 80%, 60%);
left: ${x}px;
top: ${y}px;
`;
container.appendChild(this.element);
}
update() {
this.life -= 0.05;
this.element.style.opacity = this.life;
this.element.style.transform = `scale(${this.life})`;
return this.life > 0;
}
destroy() {
this.element.remove();
}
}
let trail = [];
let hue = 0;
function addTrailPoint(x, y) {
if (!CONFIG.enableTrail) return;
trail.push(new TrailDot(x, y, hue));
hue = (hue + 10) % 360;
if (trail.length > CONFIG.trailLength) {
trail[0].destroy();
trail.shift();
}
}
// ============================================
// 🎯 元素弹跳效果
// ============================================
function addBounceEffect(element) {
if (!CONFIG.enableBounce) return;
element.style.animation = 'none';
element.offsetHeight; // 触发重排
element.style.animation = 'funBounce 0.6s ease';
setTimeout(() => {
element.style.animation = '';
}, 600);
}
// 添加弹跳动画样式
const style = document.createElement('style');
style.textContent = `
@keyframes funBounce {
0%, 100% { transform: scale(1); }
25% { transform: scale(1.2) rotate(-5deg); }
50% { transform: scale(0.9) rotate(5deg); }
75% { transform: scale(1.1) rotate(-3deg); }
}
@keyframes twinkle {
0%, 100% { opacity: 0.3; transform: scale(1); }
50% { opacity: 1; transform: scale(1.2); }
}
@keyframes fall {
0% { transform: translateY(-100px) rotate(0deg); }
100% { transform: translateY(100vh) rotate(360deg); }
}
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); }
25% { transform: translateY(-15px) rotate(5deg); }
50% { transform: translateY(5px) rotate(0deg); }
75% { transform: translateY(-10px) rotate(-5deg); }
}
@keyframes scrollEffect {
0% { transform: translateY(0) scale(0.8); opacity: 0; }
50% { transform: translateY(-20px) scale(1); opacity: 1; }
100% { transform: translateY(-40px) scale(1.2); opacity: 0; }
}
@keyframes loadEffect {
0% { transform: scale(0.3) rotate(0deg); opacity: 0; }
50% { transform: scale(1.2) rotate(180deg); opacity: 1; }
100% { transform: scale(1) rotate(360deg); opacity: 0; }
}
@keyframes weatherEffect {
0% { transform: translateX(-100px) translateY(-50px); opacity: 0; }
50% { transform: translateX(0) translateY(0); opacity: 1; }
100% { transform: translateX(100px) translateY(50px); opacity: 0; }
}
@keyframes timePulse {
0%, 100% { transform: scale(1); opacity: 0.8; }
50% { transform: scale(1.05); opacity: 1; }
}
@keyframes dynamicBackground {
0% { background-position: 0% 0%; }
50% { background-position: 100% 100%; }
100% { background-position: 0% 0%; }
}
@keyframes hoverEffect {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes keyboardEffect {
0% { transform: translateY(0) scale(1); opacity: 1; }
100% { transform: translateY(-30px) scale(1.2); opacity: 0; }
}
@keyframes themeToggle {
0% { transform: rotate(0deg) scale(1); }
50% { transform: rotate(180deg) scale(1.2); }
100% { transform: rotate(360deg) scale(1); }
}
`;
document.head.appendChild(style);
// ============================================
// ⭐ 飘落星星效果
// ============================================
class Star {
constructor() {
this.reset();
this.element = document.createElement('div');
this.element.innerHTML = ['⭐', '✨', '🌟', '💫'][Math.floor(Math.random() * 4)];
this.element.style.cssText = `
position: absolute;
font-size: ${this.size}px;
left: ${this.x}px;
top: ${this.y}px;
opacity: ${this.opacity};
pointer-events: none;
animation: fall ${this.speed}s linear infinite, twinkle 2s ease-in-out infinite;
z-index: 9999998;
`;
container.appendChild(this.element);
}
reset() {
this.x = random(0, window.innerWidth);
this.y = -50;
this.size = random(15, 30);
this.speed = random(8, 20);
this.opacity = random(0.4, 1);
}
checkReset() {
const rect = this.element.getBoundingClientRect();
if (rect.top > window.innerHeight) {
this.reset();
this.element.style.left = this.x + 'px';
this.element.style.top = this.y + 'px';
this.element.style.animation = `fall ${this.speed}s linear infinite, twinkle 2s ease-in-out infinite`;
}
}
}
let stars = [];
function initStars() {
if (!CONFIG.enableStars) return;
for (let i = 0; i < CONFIG.starCount; i++) {
setTimeout(() => {
const star = new Star();
star.y = random(-window.innerHeight, 0);
star.element.style.top = star.y + 'px';
stars.push(star);
}, i * 300);
}
}
// ============================================
// ⌨️ 打字特效
// ============================================
function createTypeEffect(x, y) {
const chars = ['✦', '✧', '★', '☆', '✯', '✡', '✵', '✶'];
const char = chars[Math.floor(Math.random() * chars.length)];
const el = document.createElement('div');
el.textContent = char;
el.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
color: ${getRandomColor()};
font-size: 20px;
pointer-events: none;
animation: typeFloat 1s ease-out forwards;
z-index: 9999999;
`;
container.appendChild(el);
setTimeout(() => el.remove(), 1000);
}
// 添加打字浮动动画
const typeStyle = document.createElement('style');
typeStyle.textContent = `
@keyframes typeFloat {
0% { transform: translateY(0) scale(1); opacity: 1; }
100% { transform: translateY(-30px) scale(1.5); opacity: 0; }
}
`;
document.head.appendChild(typeStyle);
// ============================================
// 🎛️ 控制面板
// ============================================
function createControlPanel() {
const panel = document.createElement('div');
panel.id = 'fun-effects-panel';
panel.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: linear-gradient(135deg, #ff6b6b 0%, #4ecdc4 100%);
padding: 15px;
border-radius: 15px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
z-index: 10000000;
font-family: 'Segoe UI', system-ui, sans-serif;
color: white;
min-width: 180px;
backdrop-filter: blur(10px);
`;
panel.innerHTML = `
🎉 特效控制面板
双击任意元素试试看!
`;
document.body.appendChild(panel);
// 绑定控制事件
panel.querySelector('#toggle-particles').addEventListener('change', (e) => {
CONFIG.enableParticles = e.target.checked;
});
panel.querySelector('#toggle-trail').addEventListener('change', (e) => {
CONFIG.enableTrail = e.target.checked;
if (!e.target.checked) {
trail.forEach(t => t.destroy());
trail = [];
}
});
panel.querySelector('#toggle-bounce').addEventListener('change', (e) => {
CONFIG.enableBounce = e.target.checked;
});
panel.querySelector('#toggle-stars').addEventListener('change', (e) => {
CONFIG.enableStars = e.target.checked;
stars.forEach(s => s.element.style.display = e.target.checked ? 'block' : 'none');
});
panel.querySelector('#toggle-float').addEventListener('change', (e) => {
CONFIG.enableFloat = e.target.checked;
floatEmojis.forEach(emoji => emoji.element.style.display = e.target.checked ? 'block' : 'none');
});
panel.querySelector('#toggle-scroll').addEventListener('change', (e) => {
CONFIG.enableScroll = e.target.checked;
});
panel.querySelector('#toggle-load').addEventListener('change', (e) => {
CONFIG.loadEffect = e.target.checked;
});
panel.querySelector('#toggle-time').addEventListener('change', (e) => {
CONFIG.timeDisplay = e.target.checked;
if (timeElement) {
timeElement.style.display = e.target.checked ? 'block' : 'none';
}
});
panel.querySelector('#toggle-weather').addEventListener('change', (e) => {
CONFIG.weatherEffect = e.target.checked;
});
panel.querySelector('#toggle-sound').addEventListener('change', (e) => {
CONFIG.soundEffect = e.target.checked;
});
panel.querySelector('#toggle-background').addEventListener('change', (e) => {
CONFIG.dynamicBackground = e.target.checked;
if (backgroundElement) {
backgroundElement.style.display = e.target.checked ? 'block' : 'none';
}
});
panel.querySelector('#toggle-hover').addEventListener('change', (e) => {
CONFIG.hoverEffect = e.target.checked;
});
panel.querySelector('#toggle-keyboard').addEventListener('change', (e) => {
CONFIG.keyboardEffect = e.target.checked;
});
panel.querySelector('#toggle-theme').addEventListener('change', (e) => {
CONFIG.themeToggle = e.target.checked;
const themeButton = document.getElementById('fun-effects-theme');
if (themeButton) {
themeButton.style.display = e.target.checked ? 'block' : 'none';
}
});
// 面板拖拽功能
let isDragging = false;
let currentX, currentY, initialX, initialY;
panel.addEventListener('mousedown', (e) => {
if (e.target.tagName === 'INPUT') return;
isDragging = true;
initialX = e.clientX - panel.offsetLeft;
initialY = e.clientY - panel.offsetTop;
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
panel.style.left = currentX + 'px';
panel.style.top = currentY + 'px';
panel.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
}
// ============================================
// 🚀 事件监听与动画循环
// ============================================
// 鼠标点击 - 粒子爆炸
document.addEventListener('click', (e) => {
createExplosion(e.clientX, e.clientY);
playSound('click');
});
// 鼠标移动 - 彩虹轨迹
let lastTrailTime = 0;
document.addEventListener('mousemove', (e) => {
const now = Date.now();
if (now - lastTrailTime > 20) {
addTrailPoint(e.clientX, e.clientY);
lastTrailTime = now;
}
});
// 双击 - 元素弹跳
document.addEventListener('dblclick', (e) => {
const target = e.target;
if (target && target !== container && !target.closest('#fun-effects-panel')) {
addBounceEffect(target);
createExplosion(e.clientX, e.clientY);
playSound('bounce');
}
});
// 键盘输入 - 打字特效
document.addEventListener('keydown', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) {
const rect = e.target.getBoundingClientRect();
createTypeEffect(
rect.left + random(0, rect.width),
rect.top + random(0, rect.height)
);
}
});
// 滚动 - 滚动特效
window.addEventListener('scroll', createScrollEffect);
// 动画循环
function animate() {
// 更新粒子
particles = particles.filter(particle => {
const alive = particle.update();
if (!alive) particle.destroy();
return alive;
});
// 更新轨迹
trail = trail.filter(dot => {
const alive = dot.update();
if (!alive) dot.destroy();
return alive;
});
// 检查星星
stars.forEach(star => star.checkReset());
requestAnimationFrame(animate);
}
// ============================================
// 😊 漂浮表情效果
// ============================================
class FloatEmoji {
constructor() {
this.reset();
this.element = document.createElement('div');
this.element.innerHTML = ['😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😙'][Math.floor(Math.random() * 20)];
this.element.style.cssText = `
position: absolute;
font-size: ${this.size}px;
left: ${this.x}px;
top: ${this.y}px;
pointer-events: none;
animation: float ${this.speed}s ease-in-out infinite;
z-index: 9999997;
`;
container.appendChild(this.element);
}
reset() {
this.x = random(0, window.innerWidth);
this.y = random(0, window.innerHeight);
this.size = random(20, 40);
this.speed = random(3, 6);
}
}
let floatEmojis = [];
function initFloatEmojis() {
if (!CONFIG.enableFloat) return;
for (let i = 0; i < CONFIG.floatCount; i++) {
setTimeout(() => {
floatEmojis.push(new FloatEmoji());
}, i * 500);
}
}
// ============================================
// 📜 滚动特效
// ============================================
let lastScrollY = window.scrollY;
function createScrollEffect() {
if (!CONFIG.enableScroll) return;
const scrollY = window.scrollY;
if (Math.abs(scrollY - lastScrollY) > 50) {
const emoji = ['🚀', '✨', '🌟', '⚡', '🎈', '🌈', '💨', '💫'][Math.floor(Math.random() * 8)];
const el = document.createElement('div');
el.innerHTML = emoji;
el.style.cssText = `
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 40px;
pointer-events: none;
animation: scrollEffect 1s ease-out forwards;
z-index: 9999999;
`;
container.appendChild(el);
setTimeout(() => el.remove(), 1000);
lastScrollY = scrollY;
playSound('scroll');
}
}
// ============================================
// 🎉 页面加载特效
// ============================================
function createLoadEffect() {
if (!CONFIG.loadEffect) return;
const loadEmojis = ['🎉', '✨', '🌟', '🚀', '🎈', '🎊', '🎯', '⚡'];
const emoji = loadEmojis[Math.floor(Math.random() * loadEmojis.length)];
const loadElement = document.createElement('div');
loadElement.innerHTML = emoji;
loadElement.style.cssText = `
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 80px;
pointer-events: none;
animation: loadEffect 2s ease-out forwards;
z-index: 99999999;
`;
container.appendChild(loadElement);
setTimeout(() => loadElement.remove(), 2000);
playSound('load');
}
// ============================================
// 🕒 时间显示
// ============================================
let timeElement = null;
function createTimeDisplay() {
if (!CONFIG.timeDisplay) return;
timeElement = document.createElement('div');
timeElement.id = 'fun-effects-time';
timeElement.style.cssText = `
position: fixed;
top: 20px;
left: 20px;
background: rgba(0,0,0,0.7);
color: white;
padding: 8px 12px;
border-radius: 20px;
font-family: 'Segoe UI', system-ui, sans-serif;
font-size: 14px;
backdrop-filter: blur(10px);
z-index: 9999999;
animation: timePulse 2s ease-in-out infinite;
`;
container.appendChild(timeElement);
updateTime();
setInterval(updateTime, 1000);
}
function updateTime() {
if (!timeElement || !CONFIG.timeDisplay) return;
const now = new Date();
const timeString = now.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
timeElement.textContent = timeString;
}
// ============================================
// ☁️ 实时天气效果
// ============================================
let weatherElement = null;
function getWeatherEmoji(weatherCode) {
// 根据天气代码返回对应的表情
const weatherMap = {
'Clear': '☀️',
'Clouds': '☁️',
'Rain': '🌧️',
'Drizzle': '🌦️',
'Thunderstorm': '⛈️',
'Snow': '❄️',
'Mist': '🌫️',
'Smoke': '🌫️',
'Haze': '🌫️',
'Dust': '🌫️',
'Fog': '🌫️',
'Sand': '🌫️',
'Ash': '🌫️',
'Squall': '💨',
'Tornado': '🌪️'
};
return weatherMap[weatherCode] || '🌈';
}
function updateWeatherEffect(weatherData) {
if (!CONFIG.weatherEffect) return;
const weatherMain = weatherData.weather[0].main;
const emoji = getWeatherEmoji(weatherMain);
const temp = Math.round(weatherData.main.temp);
if (!weatherElement) {
weatherElement = document.createElement('div');
weatherElement.id = 'fun-effects-weather';
weatherElement.style.cssText = `
position: fixed;
right: 20px;
top: 100px;
background: rgba(0,0,0,0.7);
color: white;
padding: 10px 15px;
border-radius: 20px;
font-family: 'Segoe UI', system-ui, sans-serif;
font-size: 14px;
backdrop-filter: blur(10px);
z-index: 9999999;
display: flex;
align-items: center;
gap: 8px;
animation: weatherEffect 3s ease-in-out infinite;
`;
container.appendChild(weatherElement);
}
weatherElement.innerHTML = `
${emoji}
`;
}
function fetchWeather(lat, lon) {
// 使用 OpenWeatherMap API 获取天气数据
const apiKey = 'YOUR_API_KEY'; // 这里需要替换为真实的 API Key
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&units=metric&appid=${apiKey}`;
fetch(url)
.then(response => response.json())
.then(data => {
updateWeatherEffect(data);
})
.catch(error => {
console.log('天气数据获取失败:', error);
// 失败时使用默认天气效果
fallbackWeatherEffect();
});
}
function fallbackWeatherEffect() {
if (!CONFIG.weatherEffect) return;
const weatherEmojis = ['🌈', '🌤️', '☀️', '☁️', '⛅', '🌥️', '🌦️', '🌧️'];
const emoji = weatherEmojis[Math.floor(Math.random() * weatherEmojis.length)];
if (!weatherElement) {
weatherElement = document.createElement('div');
weatherElement.id = 'fun-effects-weather';
weatherElement.style.cssText = `
position: fixed;
right: 20px;
top: 100px;
background: rgba(0,0,0,0.7);
color: white;
padding: 10px 15px;
border-radius: 20px;
font-family: 'Segoe UI', system-ui, sans-serif;
font-size: 14px;
backdrop-filter: blur(10px);
z-index: 9999999;
display: flex;
align-items: center;
gap: 8px;
animation: weatherEffect 3s ease-in-out infinite;
`;
container.appendChild(weatherElement);
}
weatherElement.innerHTML = `
${emoji}
天气服务不可用
`;
}
function getCurrentLocation() {
if (!CONFIG.weatherEffect) return;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
fetchWeather(lat, lon);
},
(error) => {
console.log('位置获取失败:', error);
fallbackWeatherEffect();
}
);
} else {
fallbackWeatherEffect();
}
}
function createWeatherEffect() {
// 这个函数现在只用于初始化
getCurrentLocation();
}
// ============================================
// 🔊 音效系统
// ============================================
function playSound(type) {
if (!CONFIG.soundEffect) return;
// 这里使用 Web Audio API 创建简单的音效
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
switch (type) {
case 'click':
oscillator.frequency.value = 800;
gainNode.gain.exponentialRampToValueAtTime(0.1, audioContext.currentTime + 0.05);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.2);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.2);
break;
case 'load':
oscillator.frequency.value = 600;
oscillator.frequency.exponentialRampToValueAtTime(1200, audioContext.currentTime + 0.5);
gainNode.gain.exponentialRampToValueAtTime(0.1, audioContext.currentTime + 0.1);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 1);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 1);
break;
case 'bounce':
oscillator.frequency.value = 1000;
gainNode.gain.exponentialRampToValueAtTime(0.1, audioContext.currentTime + 0.05);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.15);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.15);
break;
case 'scroll':
oscillator.frequency.value = 400;
oscillator.frequency.exponentialRampToValueAtTime(800, audioContext.currentTime + 0.3);
gainNode.gain.exponentialRampToValueAtTime(0.05, audioContext.currentTime + 0.05);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.3);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.3);
break;
}
} catch (e) {
// 音效创建失败,忽略
}
}
// ============================================
// � 动态背景
// ============================================
let backgroundElement = null;
function createDynamicBackground() {
if (!CONFIG.dynamicBackground) return;
backgroundElement = document.createElement('div');
backgroundElement.id = 'fun-effects-background';
backgroundElement.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
background: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
background-size: 400% 400%;
animation: dynamicBackground 15s ease infinite;
opacity: 0.3;
`;
document.body.appendChild(backgroundElement);
}
// ============================================
// ✨ 鼠标悬停特效
// ============================================
function initHoverEffect() {
if (!CONFIG.hoverEffect) return;
document.addEventListener('mouseover', (e) => {
const target = e.target;
if (target && target !== container && !target.closest('#fun-effects-panel') &&
!target.closest('#fun-effects-time') && !target.closest('#fun-effects-weather')) {
target.style.transition = 'transform 0.3s ease';
target.style.transform = 'scale(1.05)';
setTimeout(() => {
if (target) {
target.style.transform = 'scale(1)';
}
}, 300);
}
});
}
// ============================================
// ⌨️ 键盘特效
// ============================================
function initKeyboardEffect() {
if (!CONFIG.keyboardEffect) return;
document.addEventListener('keydown', (e) => {
const key = e.key.toUpperCase();
if (key.length === 1) {
const keyElement = document.createElement('div');
keyElement.textContent = key;
keyElement.style.cssText = `
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 60px;
font-weight: bold;
color: ${getRandomColor()};
pointer-events: none;
animation: keyboardEffect 1s ease-out forwards;
z-index: 9999999;
`;
container.appendChild(keyElement);
setTimeout(() => keyElement.remove(), 1000);
}
});
}
// ============================================
// 🎨 主题切换
// ============================================
let currentTheme = 'light';
const themes = {
light: {
background: 'linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%)',
text: '#333333',
panel: 'linear-gradient(135deg, #ff6b6b 0%, #4ecdc4 100%)'
},
dark: {
background: 'linear-gradient(45deg, #2c3e50 0%, #4b6cb7 100%)',
text: '#ffffff',
panel: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
},
neon: {
background: 'linear-gradient(45deg, #0f0c29 0%, #302b63 50%, #24243e 100%)',
text: '#00ffff',
panel: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)'
},
nature: {
background: 'linear-gradient(45deg, #a8edea 0%, #fed6e3 100%)',
text: '#2c3e50',
panel: 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)'
}
};
function createThemeToggle() {
if (!CONFIG.themeToggle) return;
const themeButton = document.createElement('div');
themeButton.id = 'fun-effects-theme';
themeButton.style.cssText = `
position: fixed;
bottom: 20px;
left: 20px;
background: rgba(0,0,0,0.7);
color: white;
padding: 10px;
border-radius: 50%;
cursor: pointer;
font-size: 20px;
backdrop-filter: blur(10px);
z-index: 9999999;
animation: themeToggle 2s ease-in-out infinite;
`;
themeButton.innerHTML = '🎨';
container.appendChild(themeButton);
themeButton.addEventListener('click', () => {
const themeKeys = Object.keys(themes);
const currentIndex = themeKeys.indexOf(currentTheme);
const nextIndex = (currentIndex + 1) % themeKeys.length;
currentTheme = themeKeys[nextIndex];
applyTheme(currentTheme);
playSound('click');
});
}
function applyTheme(themeName) {
const theme = themes[themeName];
if (backgroundElement) {
backgroundElement.style.background = theme.background;
}
const panel = document.getElementById('fun-effects-panel');
if (panel) {
panel.style.background = theme.panel;
}
}
// ============================================
// 🎬 初始化
// ============================================
function init() {
createControlPanel();
initStars();
initFloatEmojis();
createLoadEffect();
createTimeDisplay();
createDynamicBackground();
initHoverEffect();
initKeyboardEffect();
createThemeToggle();
if (CONFIG.weatherEffect) {
createWeatherEffect();
setInterval(createWeatherEffect, 300000); // 每5分钟更新一次天气
}
animate();
console.log('🎉 网页趣味特效大师已启动!');
console.log('💡 功能提示:');
console.log(' • 点击任意位置产生粒子爆炸');
console.log(' • 移动鼠标留下彩虹轨迹');
console.log(' • 双击任意元素让它弹跳');
console.log(' • 在输入框打字有特效');
console.log(' • 滚动页面触发滚动特效');
console.log(' • 页面加载时有炫酷特效');
console.log(' • 左上角显示实时时间');
console.log(' • 实时天气效果(需位置权限)');
console.log(' • 动态渐变背景');
console.log(' • 鼠标悬停元素放大效果');
console.log(' • 键盘按键特效');
console.log(' • 主题切换功能(点击左下角🎨)');
console.log(' • 各种操作有音效反馈');
console.log(' • 右上角可开关所有特效');
console.log('💡 天气功能说明:');
console.log(' • 需要位置权限才能获取实时天气');
console.log(' • 如无权限,将使用随机天气效果');
console.log(' • 天气数据每5分钟自动更新');
}
// 等待页面加载完成
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();