您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
⚒ Advanced Acellus Mod/Custom Pack – a production–quality productivity suite with persistent settings, movable/resizable widgets, inspirational quotes, custom/star wallpapers, break reminders, and more.
当前为
// ==UserScript== // @name Wizardebop 2.00 // @author Type Stuff // @description ⚒ Advanced Acellus Mod/Custom Pack – a production–quality productivity suite with persistent settings, movable/resizable widgets, inspirational quotes, custom/star wallpapers, break reminders, and more. // @version 11 // @match https://admin192a.acellus.com/student/* // @match https://admin192c.acellus.com/student/* // @license // @run-at document-start // @grant none // @namespace https://gf.qytechs.cn/users/1394549 // @icon https://img.freepik.com/free-vector/halloween-witch-hat-isolated-illustration_18591-83719.jpg // ==/UserScript== (function () { 'use strict'; /******************************************** * 1. CSS Styles ********************************************/ const style = document.createElement('style'); style.innerHTML = ` /* Animated Wallpaper & Effects */ @keyframes animated-wallpaper { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes snowfall { 0% { transform: translateY(-10px); } 100% { transform: translateY(100vh); } } @keyframes raindrop { 0% { transform: translateY(-50px); opacity: 0.7; } 100% { transform: translateY(100vh); opacity: 1; } } @keyframes floating-emoji { 0% { transform: translateY(0); opacity: 1; } 50% { transform: translateY(-30px); opacity: 0.8; } 100% { transform: translateY(0); opacity: 1; } } @keyframes color-particles { 0% { transform: translateX(0) translateY(0); opacity: 1; } 100% { transform: translateX(200px) translateY(200px); opacity: 0; } } /* Settings Button */ #settings-button { position: fixed; bottom: 20px; right: 20px; background-color: #28a745; color: white; border: none; border-radius: 5px; padding: 10px 20px; cursor: pointer; font-size: 16px; z-index: 1002; transition: background-color 0.3s ease; } #settings-button:hover { background-color: #218838; } /* Settings Menu */ #settings-menu { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 75%; max-width: 900px; max-height: 80%; overflow-y: auto; background: linear-gradient(45deg, #ffd700, #ff69b4, #e0e0e0, #f0e68c); background-size: 200% 200%; animation: animated-wallpaper 8s ease infinite; border-radius: 15px; padding: 0; box-shadow: 0px 0px 25px rgba(0, 0, 0, 0.3); z-index: 1001; display: none; overflow: hidden; } .settings-content { display: flex; width: 100%; height: 100%; border-radius: 15px; } .settings-categories { width: 25%; background-color: rgba(200, 200, 200, 0.9); padding: 20px 15px; box-sizing: border-box; margin: 0; border-top-left-radius: 15px; border-bottom-left-radius: 15px; transition: background-color 0.3s ease; } .settings-details { width: 75%; padding: 20px; display: flex; flex-direction: column; box-sizing: border-box; background-color: transparent; } #settings-menu h2 { margin-top: 0; color: #333; } .settings-categories button { width: 100%; padding: 12px; margin: 8px 0; border: none; background-color: rgba(255, 255, 255, 0.8); border-radius: 8px; cursor: pointer; text-align: left; color: #333; font-weight: bold; transition: background-color 0.3s ease, transform 0.2s ease; } .settings-categories button:hover { background-color: #007bff; color: white; transform: scale(1.05); } .category-menu { padding: 10px; background: rgba(249, 249, 249, 0.8); border-radius: 10px; display: none; } /* Additional General Settings (Break Reminder) */ /* (Will appear in the General settings menu) */ /* Overlay & Close Button */ #overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); display: none; z-index: 1000; backdrop-filter: blur(8px); } #close-settings { background: none; border: none; color: #ffffff; font-size: 1.5rem; position: absolute; top: 15px; right: 15px; cursor: pointer; transition: color 0.3s ease; } #close-settings:hover { color: #555; } #close-settings::before { content: '✖'; } /* Dark Mode Styles */ body.dark-mode { background-color: #121212; color: #e0e0e0; } .dark-mode #settings-menu { background: linear-gradient(45deg, #2f2f2f, #0e4c92, #00bcd4, #008080, #454545, #1c1c1c, #274472, #026873, #123456, #0a0a0a); background-size: 200% 200%; animation: animated-wallpaper 8s ease infinite; } .dark-mode .settings-categories { background-color: rgba(80, 80, 80, 0.7); } .dark-mode .settings-categories button { background-color: #333333; color: #e0e0e0; } .dark-mode .settings-categories button:hover { background-color: #555555; color: #ffffff; } .dark-mode .category-menu { background: rgba(68, 68, 68, 0.8); color: #e0e0e0; } .dark-mode #close-settings { color: #8b0000; } .dark-mode #close-settings:hover { color: #ff6347; } /* Apply Buttons */ #apply-appearance, #apply-wallpaper, #apply-widgets, #apply-general { margin-top: 15px; padding: 10px; background-color: #007bff; color: #ffffff; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } #apply-appearance:hover, #apply-wallpaper:hover, #apply-widgets:hover, #apply-general:hover { background-color: #0056b3; } /* Gradient Options */ .gradient-option { display: inline-block; width: 80px; height: 50px; margin: 5px; border-radius: 8px; cursor: pointer; border: 2px solid transparent; transition: border-color 0.3s ease; } .gradient-option:hover { border-color: #007bff; } #wallpaper-preview { margin-top: 10px; display: flex; flex-wrap: wrap; } .gradient-bg { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-size: 200% 200%; animation: animated-wallpaper 20s ease infinite; z-index: -1; } /* Effects Elements */ .snowflake, .raindrop, .star, .firefly, .emoji, .particle { position: fixed; top: -10px; font-size: 20px; color: white; z-index: 1005; } .snowflake { animation: snowfall 10s linear infinite; } .raindrop { animation: raindrop 5s linear infinite; font-size: 12px; color: #00bfff; } .star { animation: twinkling 3s infinite alternate; color: #fffacd; font-size: 10px; } .firefly { background-color: yellow; width: 10px; height: 10px; border-radius: 50%; animation: twinkling 2s infinite alternate; } .emoji { animation: floating-emoji 4s infinite alternate; font-size: 30px; } .particle { animation: color-particles 6s linear infinite; background-color: #ff4081; border-radius: 50%; width: 10px; height: 10px; } /* Clock Widget */ #clock-widget { position: fixed; top: 20px; left: 20px; background-color: #333; color: #fff; padding: 10px 20px; border-radius: 8px; font-family: Arial, sans-serif; font-size: 18px; z-index: 1005; user-select: none; cursor: grab; } /* Resize Handle for Widgets */ .resize-handle { position: absolute; width: 10px; height: 10px; background: #007bff; bottom: 0; right: 0; cursor: se-resize; z-index: 10; } /* Good Day Quote Widget & Progress Bar */ #good-day-quote-widget { position: fixed; top: 50px; right: 20px; background: rgba(0,0,0,0.8); color: #fff; padding: 10px 15px; border-radius: 8px; font-family: Arial, sans-serif; z-index: 1006; width: 300px; font-size: 14px; text-align: center; } #good-day-quote-widget .quote-progress { position: absolute; bottom: 0; left: 0; height: 4px; background: #28a745; width: 100%; } `; document.head.appendChild(style); /******************************************** * 2. Helper: Movable & Resizable Widgets ********************************************/ function makeMovableResizable(widget, widgetKey) { // Load saved position from localStorage (if any) const savedPos = localStorage.getItem('widget_' + widgetKey + '_position'); if (savedPos) { try { const pos = JSON.parse(savedPos); widget.style.left = pos.left; widget.style.top = pos.top; } catch (e) { /* ignore error */ } } // Load saved size (if any) const savedSize = localStorage.getItem('widget_' + widgetKey + '_size'); if (savedSize) { try { const size = JSON.parse(savedSize); widget.style.width = size.width; widget.style.height = size.height; } catch (e) { /* ignore error */ } } // Ensure widget is fixed positioned widget.style.position = 'fixed'; // DRAG: Only drag when not clicking on the resize-handle widget.addEventListener('mousedown', function(e) { if (e.target.classList.contains('resize-handle')) return; const startX = e.clientX; const startY = e.clientY; const origLeft = parseInt(widget.style.left, 10) || 0; const origTop = parseInt(widget.style.top, 10) || 0; function onMouseMove(e) { widget.style.left = (origLeft + (e.clientX - startX)) + 'px'; widget.style.top = (origTop + (e.clientY - startY)) + 'px'; } function onMouseUp() { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); const pos = { left: widget.style.left, top: widget.style.top }; localStorage.setItem('widget_' + widgetKey + '_position', JSON.stringify(pos)); } document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); // RESIZE: Add a resize handle if not already present let resizeHandle = widget.querySelector('.resize-handle'); if (!resizeHandle) { resizeHandle = document.createElement('div'); resizeHandle.className = 'resize-handle'; widget.appendChild(resizeHandle); } resizeHandle.addEventListener('mousedown', function(e) { e.stopPropagation(); const startX = e.clientX; const startY = e.clientY; const origWidth = widget.offsetWidth; const origHeight = widget.offsetHeight; function onMouseMove(e) { widget.style.width = (origWidth + (e.clientX - startX)) + 'px'; widget.style.height = (origHeight + (e.clientY - startY)) + 'px'; } function onMouseUp() { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); const size = { width: widget.style.width, height: widget.style.height }; localStorage.setItem('widget_' + widgetKey + '_size', JSON.stringify(size)); } document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); } /******************************************** * 3. Settings Menu & Overlay ********************************************/ const settingsButton = document.createElement('button'); settingsButton.id = 'settings-button'; settingsButton.textContent = 'Settings'; document.body.appendChild(settingsButton); // The settings menu now includes an extra “Break Reminder” option in General const settingsMenu = document.createElement('div'); settingsMenu.id = 'settings-menu'; settingsMenu.innerHTML = ` <div class="settings-content"> <div class="settings-categories"> <button class="category-btn" data-category="general">General</button> <button class="category-btn" data-category="appearance">Appearance</button> <button class="category-btn" data-category="wallpaper">Wallpaper</button> <button class="category-btn" data-category="effects">Effects</button> <button class="category-btn" data-category="widgets">Widgets</button> </div> <div class="settings-details"> <!-- General Settings --> <div class="category-menu" id="general-menu"> <label><input type="checkbox" id="enable-notifications"> Enable Notifications</label><br> <label><input type="checkbox" id="auto-save-progress"> Auto-Save Progress</label><br> <label><input type="checkbox" id="focus-mode"> Enable Focus Mode</label><br> <label><input type="checkbox" id="auto-dark-mode"> Enable Auto Dark Mode</label><br> <label><input type="checkbox" id="disable-animations"> Disable Animations</label><br> <label><input type="checkbox" id="enable-break-reminder"> Enable Break Reminder</label><br> <label>Break Interval (minutes): <input type="number" id="break-interval" min="5" max="60" value="30"> </label><br> <button id="apply-general">Apply General Settings</button> </div> <!-- Appearance Settings --> <div class="category-menu" id="appearance-menu"> <h2>Appearance Settings</h2> <label>Theme: <select id="theme-selector"> <option value="light">Light</option> <option value="dark">Dark</option> </select> </label><br> <label>Gradient Speed: <input type="range" id="gradient-speed" min="5" max="30" step="1" value="20"> </label><br> <label><input type="checkbox" id="enable-animations"> Enable Animations</label><br> <label><input type="checkbox" id="enable-background-blur"> Enable Background Blur</label><br> <button id="apply-appearance">Apply</button> </div> <!-- Wallpaper Settings --> <div class="category-menu" id="wallpaper-menu"> <h2>Wallpaper Settings</h2> <label>Custom Wallpaper (Image/GIF URL): <input type="text" id="custom-wallpaper-url" placeholder="Enter image or gif URL" /> </label><br> <label><input type="checkbox" id="enable-custom-wallpaper"> Enable Custom Wallpaper</label><br> <label><input type="checkbox" id="enable-star-wallpaper"> Enable Star Wallpaper</label><br> <label>Star Density: <input type="range" id="star-density" min="10" max="200" step="10" value="50"> </label><br> <button id="apply-wallpaper">Apply Wallpaper</button> <div id="wallpaper-preview"> <!-- Gradient options will be appended here --> </div> </div> <!-- Effects Settings --> <div class="category-menu" id="effects-menu"> <h2>Visual Effects</h2> <label><input type="checkbox" id="enable-snowfall"> Enable Snowfall Effect</label><br> <label><input type="checkbox" id="enable-rain"> Enable Minecraft-Like Rain Effect</label><br> <label><input type="checkbox" id="enable-stars"> Enable Twinkling Stars Effect</label><br> <label><input type="checkbox" id="enable-fireflies"> Enable Fireflies Effect</label><br> <label><input type="checkbox" id="enable-floating-emojis"> Enable Floating Emojis</label><br> <label><input type="checkbox" id="enable-particles"> Enable Color Particles</label><br> <button id="apply-effects">Apply Effects</button> </div> <!-- Widgets Settings --> <div class="category-menu" id="widgets-menu"> <h2>Widgets</h2> <label><input type="checkbox" id="enable-clock-widget"> Enable Clock Widget</label><br> <label><input type="checkbox" id="enable-pomodoro-widget"> Enable Pomodoro Timer</label><br> <label>Pomodoro Duration (minutes): <input type="number" id="pomodoro-duration" min="1" max="60" value="25"> </label><br> <label><input type="checkbox" id="enable-todo-widget"> Enable To-Do List</label><br> <label><input type="checkbox" id="enable-good-day-quote"> Enable Good Day Quote</label><br> <button id="apply-widgets">Apply Widgets</button> </div> </div> </div> <button id="close-settings"></button> `; document.body.appendChild(settingsMenu); settingsMenu.style.display = 'none'; const overlay = document.createElement('div'); overlay.id = 'overlay'; document.body.appendChild(overlay); overlay.style.display = 'none'; /******************************************** * 4. Widgets: Clock, Pomodoro, To-Do, Good Day Quote ********************************************/ // Clock Widget const clockWidget = document.createElement('div'); clockWidget.id = 'clock-widget'; document.body.appendChild(clockWidget); clockWidget.style.display = 'none'; setInterval(() => { const now = new Date(); clockWidget.textContent = now.toLocaleTimeString(); }, 1000); makeMovableResizable(clockWidget, 'clock-widget'); // Pomodoro Timer Widget const pomodoroWidget = document.createElement('div'); pomodoroWidget.id = 'pomodoro-widget'; pomodoroWidget.innerHTML = ` <h3>Pomodoro Timer</h3> <div class="time">25:00</div> <button id="pomodoro-start-stop">Start</button> <button id="pomodoro-reset">Reset</button> `; document.body.appendChild(pomodoroWidget); pomodoroWidget.style.display = 'none'; makeMovableResizable(pomodoroWidget, 'pomodoro-widget'); let pomodoroInterval = null; let pomodoroTime = 25 * 60; // will be updated from settings let pomodoroRunning = false; function updatePomodoroDisplay() { const minutes = String(Math.floor(pomodoroTime / 60)).padStart(2, '0'); const seconds = String(pomodoroTime % 60).padStart(2, '0'); pomodoroWidget.querySelector('.time').textContent = `${minutes}:${seconds}`; } document.getElementById('pomodoro-start-stop').addEventListener('click', () => { if (!pomodoroRunning) { pomodoroInterval = setInterval(() => { if (pomodoroTime > 0) { pomodoroTime--; updatePomodoroDisplay(); } else { clearInterval(pomodoroInterval); pomodoroRunning = false; document.getElementById('pomodoro-start-stop').textContent = 'Start'; alert('Pomodoro session completed! Take a short break.'); } }, 1000); pomodoroRunning = true; document.getElementById('pomodoro-start-stop').textContent = 'Pause'; } else { clearInterval(pomodoroInterval); pomodoroRunning = false; document.getElementById('pomodoro-start-stop').textContent = 'Start'; } }); document.getElementById('pomodoro-reset').addEventListener('click', () => { clearInterval(pomodoroInterval); const duration = parseInt(document.getElementById('pomodoro-duration').value, 10) || 25; pomodoroTime = duration * 60; pomodoroRunning = false; updatePomodoroDisplay(); document.getElementById('pomodoro-start-stop').textContent = 'Start'; }); // To-Do List Widget const todoWidget = document.createElement('div'); todoWidget.id = 'todo-widget'; todoWidget.innerHTML = ` <h3>To-Do List</h3> <input type="text" id="todo-input" placeholder="Add new task..."> <ul id="todo-list"></ul> `; document.body.appendChild(todoWidget); todoWidget.style.display = 'none'; makeMovableResizable(todoWidget, 'todo-widget'); document.getElementById('todo-input').addEventListener('keypress', (e) => { if (e.key === 'Enter') { const task = e.target.value.trim(); if (task !== '') { addTodoItem(task); e.target.value = ''; } } }); function addTodoItem(task) { const li = document.createElement('li'); li.textContent = task; const removeBtn = document.createElement('button'); removeBtn.textContent = '✖'; removeBtn.addEventListener('click', () => { li.remove(); saveTodoList(); }); li.appendChild(removeBtn); document.getElementById('todo-list').appendChild(li); saveTodoList(); } function saveTodoList() { const items = []; document.querySelectorAll('#todo-list li').forEach(li => { items.push(li.firstChild.textContent); }); localStorage.setItem('todo-list', JSON.stringify(items)); } function loadTodoList() { const items = JSON.parse(localStorage.getItem('todo-list') || '[]'); items.forEach(task => addTodoItem(task)); } loadTodoList(); // Good Day Quote Widget (Ephemeral: shows for 10 seconds with progress bar) let goodDayQuoteWidget = null; let goodDayQuoteTimeout = null; const goodDayQuotes = []; for (let i = 1; i <= 200; i++) { goodDayQuotes.push(`Inspiration #${i}: Have a fantastic day and keep pushing forward!`); } function getRandomGoodDayQuote() { const index = Math.floor(Math.random() * goodDayQuotes.length); return goodDayQuotes[index]; } function showGoodDayQuote() { if (goodDayQuoteWidget) return; goodDayQuoteWidget = document.createElement('div'); goodDayQuoteWidget.id = 'good-day-quote-widget'; goodDayQuoteWidget.textContent = getRandomGoodDayQuote(); const progressBar = document.createElement('div'); progressBar.className = 'quote-progress'; progressBar.style.transition = 'width 10s linear'; goodDayQuoteWidget.appendChild(progressBar); document.body.appendChild(goodDayQuoteWidget); makeMovableResizable(goodDayQuoteWidget, 'good-day-quote-widget'); void progressBar.offsetWidth; // force reflow progressBar.style.width = '0%'; goodDayQuoteTimeout = setTimeout(() => { if (goodDayQuoteWidget) { goodDayQuoteWidget.remove(); goodDayQuoteWidget = null; } }, 10000); } function handleGoodDayQuote() { const enabled = localStorage.getItem('enable-good-day-quote') === 'true' || document.getElementById('enable-good-day-quote').checked; if (enabled) { if (Math.random() < 0.5) { showGoodDayQuote(); } setInterval(() => { if (Math.random() < 0.5) { showGoodDayQuote(); } }, 10 * 60 * 1000); } else { if (goodDayQuoteWidget) { goodDayQuoteWidget.remove(); goodDayQuoteWidget = null; } if (goodDayQuoteTimeout) { clearTimeout(goodDayQuoteTimeout); goodDayQuoteTimeout = null; } } } /******************************************** * 5. Break Reminder (New Feature) ********************************************/ let breakReminderInterval; function initBreakReminder() { if (breakReminderInterval) clearInterval(breakReminderInterval); const interval = parseInt(document.getElementById('break-interval').value, 10) || 30; breakReminderInterval = setInterval(() => { alert('Time for a break! Take a moment to relax.'); }, interval * 60 * 1000); } /******************************************** * 6. Star Wallpaper Effect ********************************************/ function initStarWallpaper() { // Remove any existing star wallpaper canvas and gradient backgrounds const oldCanvas = document.getElementById('star-wallpaper-canvas'); if (oldCanvas) { oldCanvas.remove(); } const oldGradient = document.querySelector('.gradient-bg'); if (oldGradient) { oldGradient.remove(); } // Create a full-screen canvas for the star wallpaper const canvas = document.createElement('canvas'); canvas.id = 'star-wallpaper-canvas'; canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.zIndex = '-2'; canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); const ctx = canvas.getContext('2d'); // Calculate the center of the canvas (used for projection and orbits) const centerX = canvas.width / 2; const centerY = canvas.height / 2; // Draw a deep–black, spacy overlay using a radial gradient function drawBackground() { const gradient = ctx.createRadialGradient(centerX, centerY, canvas.width / 4, centerX, centerY, canvas.width); gradient.addColorStop(0, 'rgba(0, 0, 0, 0.95)'); gradient.addColorStop(1, 'rgba(0, 0, 0, 1)'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); } // Simple perspective projection function using a z–value (for 3D effect) function project(x, y, z) { const scale = 1 / z; // Larger z => further away => smaller scale return { x: (x - centerX) * scale + centerX, y: (y - centerY) * scale + centerY, scale }; } // Generate a field of stars with a random z coordinate for depth const stars = []; const densityInput = document.getElementById('star-density'); const starCount = densityInput ? parseInt(densityInput.value, 10) : 50; for (let i = 0; i < starCount; i++) { stars.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, z: Math.random() * 1 + 0.5, // z between 0.5 and 1.5 baseSize: Math.random() * 2 + 0.5, alpha: Math.random(), alphaChange: (Math.random() * 0.001) + 0.0005 // slower twinkling }); } // Generate cosmic dust particles with depth const dustParticles = []; for (let i = 0; i < 100; i++) { dustParticles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, z: Math.random() * 1 + 0.5, baseSize: Math.random() * 1.5 + 0.5, vx: (Math.random() - 0.5) * 0.1, vy: (Math.random() - 0.5) * 0.1, alpha: Math.random() * 0.5 + 0.1 }); } // Define the central sun (larger and circular) const sun = { x: centerX, y: centerY, size: 40, color: 'yellow' }; // Define solar system–inspired planets with 3D–like orbits // The "inclination" factor tilts the orbits. const inclination = 0.7; const solarPlanets = [ { name: "Mercury", orbitRadius: 50, size: 3, color: "#bebebe", speed: 0.01, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Venus", orbitRadius: 80, size: 5, color: "#e6c27a", speed: 0.008, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Earth", orbitRadius: 110, size: 5.5, color: "#3a81f1", speed: 0.006, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Mars", orbitRadius: 140, size: 4, color: "#c1440e", speed: 0.005, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Jupiter", orbitRadius: 200, size: 10, color: "#d3a068", speed: 0.0035, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Saturn", orbitRadius: 250, size: 9, color: "#e6d0a8", speed: 0.0025, angle: Math.random() * Math.PI * 2, ring: true }, { name: "Uranus", orbitRadius: 300, size: 7, color: "#81d1e6", speed: 0.002, angle: Math.random() * Math.PI * 2, ring: false }, { name: "Neptune", orbitRadius: 350, size: 7, color: "#3a66e6", speed: 0.0015, angle: Math.random() * Math.PI * 2, ring: false } ]; // For each planet, compute its initial position and a depth indicator. // Here we use the unmodified sine of the angle to determine depth: solarPlanets.forEach(planet => { // Make the orbit wider horizontally by multiplying the orbitRadius by 1.3 for the x coordinate. planet.xPos = centerX + planet.orbitRadius * 1.3 * Math.cos(planet.angle); planet.yPos = centerY + planet.orbitRadius * Math.sin(planet.angle) * inclination; planet.depth = Math.sin(planet.angle); // negative => behind the sun, positive => in front }); // Array for shooting stars const shootingStars = []; // Animation loop: update positions and redraw everything function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw the deep–black, spacy background drawBackground(); // Draw twinkling stars with perspective projection stars.forEach(star => { star.alpha += star.alphaChange; if (star.alpha <= 0 || star.alpha >= 1) { star.alphaChange = -star.alphaChange; } const p = project(star.x, star.y, star.z); const size = star.baseSize * p.scale; ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI * 2); ctx.fillStyle = `rgba(255,255,255,${star.alpha.toFixed(2)})`; ctx.fill(); }); // Update and draw cosmic dust particles with perspective dustParticles.forEach(dust => { dust.x += dust.vx; dust.y += dust.vy; if (dust.x < 0) dust.x = canvas.width; if (dust.x > canvas.width) dust.x = 0; if (dust.y < 0) dust.y = canvas.height; if (dust.y > canvas.height) dust.y = 0; const p = project(dust.x, dust.y, dust.z); const size = dust.baseSize * p.scale; ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI * 2); ctx.fillStyle = `rgba(200,200,200,${dust.alpha.toFixed(2)})`; ctx.fill(); }); // --- Update Solar Planets --- // Update each planet's orbit angle and recalc positions solarPlanets.forEach(planet => { planet.angle += planet.speed; planet.xPos = centerX + planet.orbitRadius * 1.3 * Math.cos(planet.angle); planet.yPos = centerY + planet.orbitRadius * Math.sin(planet.angle) * inclination; planet.depth = Math.sin(planet.angle); }); // Separate planets into two groups: those behind and those in front of the sun const behindPlanets = solarPlanets.filter(planet => planet.depth < 0); const frontPlanets = solarPlanets.filter(planet => planet.depth >= 0); // Draw planets behind the sun behindPlanets.forEach(planet => { const p = project(planet.xPos, planet.yPos, 1 - planet.depth); const size = planet.size * p.scale; ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI * 2); ctx.fillStyle = planet.color; ctx.fill(); if (planet.ring) { // Draw Saturn's ring const ringOuterRadius = size + 8; const ringInnerRadius = size + 3; ctx.save(); ctx.beginPath(); ctx.ellipse(p.x, p.y, ringOuterRadius, ringOuterRadius * 0.5, 0, 0, Math.PI * 2); const ringGradient = ctx.createRadialGradient(p.x, p.y, ringInnerRadius, p.x, p.y, ringOuterRadius); ringGradient.addColorStop(0, 'rgba(230, 200, 150, 0.8)'); ringGradient.addColorStop(1, 'rgba(210, 180, 130, 0.5)'); ctx.fillStyle = ringGradient; ctx.fill(); ctx.globalCompositeOperation = 'destination-out'; ctx.beginPath(); ctx.ellipse(p.x, p.y, ringInnerRadius, ringInnerRadius * 0.5, 0, 0, Math.PI * 2); ctx.fill(); ctx.globalCompositeOperation = 'source-over'; ctx.restore(); } }); // Draw the central sun (always on top of the "behind" layer) ctx.beginPath(); ctx.arc(sun.x, sun.y, sun.size, 0, Math.PI * 2); ctx.fillStyle = sun.color; ctx.fill(); // Draw planets in front of the sun frontPlanets.forEach(planet => { const p = project(planet.xPos, planet.yPos, 1 - planet.depth); const size = planet.size * p.scale; ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI * 2); ctx.fillStyle = planet.color; ctx.fill(); if (planet.ring) { const ringOuterRadius = size + 8; const ringInnerRadius = size + 3; ctx.save(); ctx.beginPath(); ctx.ellipse(p.x, p.y, ringOuterRadius, ringOuterRadius * 0.5, 0, 0, Math.PI * 2); const ringGradient = ctx.createRadialGradient(p.x, p.y, ringInnerRadius, p.x, p.y, ringOuterRadius); ringGradient.addColorStop(0, 'rgba(230, 200, 150, 0.8)'); ringGradient.addColorStop(1, 'rgba(210, 180, 130, 0.5)'); ctx.fillStyle = ringGradient; ctx.fill(); ctx.globalCompositeOperation = 'destination-out'; ctx.beginPath(); ctx.ellipse(p.x, p.y, ringInnerRadius, ringInnerRadius * 0.5, 0, 0, Math.PI * 2); ctx.fill(); ctx.globalCompositeOperation = 'source-over'; ctx.restore(); } }); // Occasionally spawn a shooting star (with slower speeds) if (Math.random() < 0.003) { shootingStars.push({ x: Math.random() * canvas.width, y: 0, vx: (Math.random() * 2) + 3, vy: (Math.random() * 1) + 1, length: Math.random() * 60 + 20, life: 0, maxLife: 40 }); } // Update and draw shooting stars for (let i = shootingStars.length - 1; i >= 0; i--) { const s = shootingStars[i]; s.x += s.vx; s.y += s.vy; s.life++; ctx.beginPath(); ctx.moveTo(s.x, s.y); ctx.lineTo(s.x - s.length, s.y - s.length * (s.vy / s.vx)); ctx.strokeStyle = 'white'; ctx.lineWidth = 2; ctx.stroke(); if (s.life > s.maxLife) { shootingStars.splice(i, 1); } } requestAnimationFrame(animate); } animate(); // Adjust canvas size on window resize window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); } /******************************************** * 7. Settings Button & Menu Event Listeners ********************************************/ function openSettingsMenu() { overlay.style.display = 'block'; settingsMenu.style.display = 'flex'; } function closeSettingsMenu() { overlay.style.display = 'none'; settingsMenu.style.display = 'none'; document.querySelectorAll('.category-menu').forEach(menu => { menu.style.display = 'none'; }); } settingsButton.addEventListener('click', () => { const code = prompt('Enter the password:'); if (code === '123') { openSettingsMenu(); } else { alert('Incorrect password'); } }); overlay.addEventListener('click', closeSettingsMenu); document.getElementById('close-settings').addEventListener('click', closeSettingsMenu); document.querySelectorAll('.category-btn').forEach(button => { button.addEventListener('click', (e) => { const category = e.target.getAttribute('data-category'); const menu = document.getElementById(`${category}-menu`); document.querySelectorAll('.category-menu').forEach(menu => { menu.style.display = 'none'; }); if (menu) { menu.style.display = 'block'; } }); }); /******************************************** * 8. Wallpaper Functions & Gradient Options ********************************************/ function applyCustomWallpaper(url) { const gradientBg = document.querySelector('.gradient-bg'); if (gradientBg) gradientBg.remove(); if (url && url.trim() !== '') { document.body.style.backgroundImage = `url('${url}')`; document.body.style.backgroundPosition = 'center'; document.body.style.backgroundRepeat = 'no-repeat'; document.body.style.backgroundSize = 'cover'; } else { document.body.style.backgroundImage = ''; } } document.getElementById('apply-wallpaper').addEventListener('click', () => { const enableCustom = document.getElementById('enable-custom-wallpaper').checked; const enableStar = document.getElementById('enable-star-wallpaper').checked; const url = document.getElementById('custom-wallpaper-url').value; saveSetting('enable-custom-wallpaper', enableCustom); saveSetting('custom-wallpaper-url', url); saveSetting('enable-star-wallpaper', enableStar); if (enableStar) { initStarWallpaper(); } else if (enableCustom) { applyCustomWallpaper(url); } else { document.body.style.backgroundImage = ''; const selectedGradient = localStorage.getItem('selected-gradient'); if (selectedGradient) { applyAnimatedGradient(selectedGradient); } } }); // Gradient Options const gradients = [ 'linear-gradient(90deg, #ff7e5f, #feb47b)', 'linear-gradient(90deg, #6a11cb, #2575fc)', 'linear-gradient(90deg, #43cea2, #185a9d)', 'linear-gradient(90deg, #ff9a9e, #fad0c4)', 'linear-gradient(90deg, #a1c4fd, #c2e9fb)', 'linear-gradient(90deg, #667eea, #764ba2)', 'linear-gradient(90deg, #89f7fe, #66a6ff)', ]; const wallpaperPreview = document.getElementById('wallpaper-preview'); gradients.forEach((gradient) => { const gradientDiv = document.createElement('div'); gradientDiv.className = 'gradient-option'; gradientDiv.style.background = gradient; gradientDiv.dataset.gradient = gradient; gradientDiv.addEventListener('click', () => { applyAnimatedGradient(gradient); saveSetting('selected-gradient', gradient); }); wallpaperPreview.appendChild(gradientDiv); }); function applyAnimatedGradient(gradient) { let gradientBg = document.querySelector('.gradient-bg'); if (!gradientBg) { gradientBg = document.createElement('div'); gradientBg.className = 'gradient-bg'; document.body.appendChild(gradientBg); } gradientBg.style.background = gradient; } /******************************************** * 9. Appearance Settings Functions ********************************************/ function applyTheme() { const theme = document.getElementById('theme-selector').value; saveSetting('theme-selector', theme); if (theme === 'dark') { document.body.classList.add('dark-mode'); } else { document.body.classList.remove('dark-mode'); } } document.getElementById('apply-appearance').addEventListener('click', () => { const customWallpaperUrl = document.getElementById('custom-wallpaper-url').value; saveSetting('custom-wallpaper-url', customWallpaperUrl); applyTheme(); const blur = document.getElementById('enable-background-blur').checked; const gradientSpeed = document.getElementById('gradient-speed').value; saveSetting('enable-background-blur', blur); saveSetting('gradient-speed', gradientSpeed); const gradientBg = document.querySelector('.gradient-bg'); if (gradientBg) { gradientBg.style.animationDuration = `${gradientSpeed}s`; } if (blur) { document.body.style.backdropFilter = 'blur(8px)'; } else { document.body.style.backdropFilter = ''; } }); /******************************************** * 10. Effects Settings Listener ********************************************/ document.getElementById('apply-effects').addEventListener('click', () => { const snowfall = document.getElementById('enable-snowfall').checked; const rain = document.getElementById('enable-rain').checked; const starsEff = document.getElementById('enable-stars').checked; const fireflies = document.getElementById('enable-fireflies').checked; const floatingEmojis = document.getElementById('enable-floating-emojis').checked; const particles = document.getElementById('enable-particles').checked; saveSetting('enable-snowfall', snowfall); saveSetting('enable-rain', rain); saveSetting('enable-stars', starsEff); saveSetting('enable-fireflies', fireflies); saveSetting('enable-floating-emojis', floatingEmojis); saveSetting('enable-particles', particles); toggleEffect('snowflake', snowfall); toggleEffect('raindrop', rain); toggleEffect('star', starsEff); toggleEffect('firefly', fireflies); toggleEffect('emoji', floatingEmojis); toggleEffect('particle', particles); }); function toggleEffect(type, enable) { let effectIntervals = {}; if (enable) { if (!effectIntervals[type]) { effectIntervals[type] = setInterval(() => createEffect(type), 500); } } else { clearInterval(effectIntervals[type]); delete effectIntervals[type]; document.querySelectorAll(`.${type}`).forEach(el => el.remove()); } } function createEffect(type) { const effectElement = document.createElement('div'); effectElement.className = type; if (type === 'snowflake') { effectElement.textContent = '❄'; } else if (type === 'raindrop') { effectElement.textContent = '|'; } else if (type === 'star') { effectElement.textContent = '★'; } else if (type === 'emoji') { effectElement.textContent = ['🌟', '✨', '❤️', '😊', '🔥', '🌈'][Math.floor(Math.random() * 6)]; } effectElement.style.left = Math.random() * window.innerWidth + 'px'; effectElement.style.animationDuration = (Math.random() * 5 + 5) + 's'; document.body.appendChild(effectElement); setTimeout(() => effectElement.remove(), 10000); } /******************************************** * 11. Widgets Settings Listener ********************************************/ document.getElementById('apply-widgets').addEventListener('click', () => { const clockEnabled = document.getElementById('enable-clock-widget').checked; saveSetting('enable-clock-widget', clockEnabled); clockWidget.style.display = clockEnabled ? 'block' : 'none'; const pomodoroEnabled = document.getElementById('enable-pomodoro-widget').checked; saveSetting('enable-pomodoro-widget', pomodoroEnabled); pomodoroWidget.style.display = pomodoroEnabled ? 'block' : 'none'; const todoEnabled = document.getElementById('enable-todo-widget').checked; saveSetting('enable-todo-widget', todoEnabled); todoWidget.style.display = todoEnabled ? 'block' : 'none'; const goodDayEnabled = document.getElementById('enable-good-day-quote').checked; saveSetting('enable-good-day-quote', goodDayEnabled); handleGoodDayQuote(); // Update Pomodoro Duration const pomodoroDuration = parseInt(document.getElementById('pomodoro-duration').value, 10) || 25; saveSetting('pomodoro-duration', pomodoroDuration); pomodoroTime = pomodoroDuration * 60; updatePomodoroDisplay(); }); /******************************************** * 12. Save & Load Settings Utility ********************************************/ const saveSetting = (id, value) => { localStorage.setItem(id, value); }; const applySavedSettings = () => { // General document.getElementById('focus-mode').checked = localStorage.getItem('focus-mode') === 'true'; document.getElementById('auto-dark-mode').checked = localStorage.getItem('auto-dark-mode') === 'true'; document.getElementById('disable-animations').checked = localStorage.getItem('disable-animations') === 'true'; document.getElementById('enable-break-reminder').checked = localStorage.getItem('enable-break-reminder') === 'true'; const breakInterval = localStorage.getItem('break-interval'); if (breakInterval) { document.getElementById('break-interval').value = breakInterval; } // Appearance const theme = localStorage.getItem('theme-selector'); if (theme) { document.getElementById('theme-selector').value = theme; applyTheme(); } const customWallpaperUrl = localStorage.getItem('custom-wallpaper-url'); if (customWallpaperUrl) { document.getElementById('custom-wallpaper-url').value = customWallpaperUrl; } const enableCustom = localStorage.getItem('enable-custom-wallpaper') === 'true'; document.getElementById('enable-custom-wallpaper').checked = enableCustom; const enableStar = localStorage.getItem('enable-star-wallpaper') === 'true'; document.getElementById('enable-star-wallpaper').checked = enableStar; if (enableStar) { initStarWallpaper(); } else if (enableCustom) { applyCustomWallpaper(customWallpaperUrl); } const gradientSpeed = localStorage.getItem('gradient-speed'); if (gradientSpeed) { document.getElementById('gradient-speed').value = gradientSpeed; const gradientBg = document.querySelector('.gradient-bg'); if (gradientBg) { gradientBg.style.animationDuration = `${gradientSpeed}s`; } } // Effects document.getElementById('enable-snowfall').checked = localStorage.getItem('enable-snowfall') === 'true'; document.getElementById('enable-rain').checked = localStorage.getItem('enable-rain') === 'true'; document.getElementById('enable-stars').checked = localStorage.getItem('enable-stars') === 'true'; document.getElementById('enable-fireflies').checked = localStorage.getItem('enable-fireflies') === 'true'; document.getElementById('enable-floating-emojis').checked = localStorage.getItem('enable-floating-emojis') === 'true'; document.getElementById('enable-particles').checked = localStorage.getItem('enable-particles') === 'true'; // Widgets document.getElementById('enable-clock-widget').checked = localStorage.getItem('enable-clock-widget') === 'true'; clockWidget.style.display = (localStorage.getItem('enable-clock-widget') === 'true') ? 'block' : 'none'; document.getElementById('enable-pomodoro-widget').checked = localStorage.getItem('enable-pomodoro-widget') === 'true'; pomodoroWidget.style.display = (localStorage.getItem('enable-pomodoro-widget') === 'true') ? 'block' : 'none'; document.getElementById('enable-todo-widget').checked = localStorage.getItem('enable-todo-widget') === 'true'; todoWidget.style.display = (localStorage.getItem('enable-todo-widget') === 'true') ? 'block' : 'none'; document.getElementById('enable-good-day-quote').checked = localStorage.getItem('enable-good-day-quote') === 'true'; handleGoodDayQuote(); const savedPomodoroDuration = localStorage.getItem('pomodoro-duration'); if (savedPomodoroDuration) { document.getElementById('pomodoro-duration').value = savedPomodoroDuration; pomodoroTime = parseInt(savedPomodoroDuration, 10) * 60; updatePomodoroDisplay(); } // Additional general settings applyFocusMode(document.getElementById('focus-mode').checked); applyAutoDarkMode(document.getElementById('auto-dark-mode').checked); applyDisableAnimations(document.getElementById('disable-animations').checked); if (document.getElementById('enable-break-reminder').checked) { initBreakReminder(); } }; applySavedSettings(); /******************************************** * 13. Additional General Settings Functions ********************************************/ function applyFocusMode(enable) { if (enable) { document.body.style.filter = "blur(0)"; document.querySelectorAll('.distracting-element').forEach(el => el.style.display = 'none'); } else { document.querySelectorAll('.distracting-element').forEach(el => el.style.display = ''); } } function autoDarkMode() { const now = new Date(); const hour = now.getHours(); if (hour >= 18 || hour < 6) { document.body.classList.add('dark-mode'); } else { document.body.classList.remove('dark-mode'); } } function applyAutoDarkMode(enable) { if (enable) { setInterval(autoDarkMode, 60000); autoDarkMode(); } } function applyDisableAnimations(enable) { if (enable) { document.querySelectorAll("*").forEach(el => { el.style.animation = "none"; el.style.transition = "none"; }); } } document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { checkbox.addEventListener('change', function () { saveSetting(this.id, this.checked); }); }); document.getElementById('theme-selector').addEventListener('change', applyTheme); /******************************************** * 14. Break Reminder – Hook into General Settings Apply ********************************************/ document.getElementById('apply-general').addEventListener('click', () => { const focusMode = document.getElementById('focus-mode').checked; const autoDarkModeEnabled = document.getElementById('auto-dark-mode').checked; const disableAnimations = document.getElementById('disable-animations').checked; const breakReminder = document.getElementById('enable-break-reminder').checked; const breakInterval = document.getElementById('break-interval').value; saveSetting('focus-mode', focusMode); saveSetting('auto-dark-mode', autoDarkModeEnabled); saveSetting('disable-animations', disableAnimations); saveSetting('enable-break-reminder', breakReminder); saveSetting('break-interval', breakInterval); applyFocusMode(focusMode); applyAutoDarkMode(autoDarkModeEnabled); applyDisableAnimations(disableAnimations); if (breakReminder) { initBreakReminder(); } else { clearInterval(breakReminderInterval); } }); // End of Script – Your Ultimate Productivity Suite is ready for production! })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址