您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在页面上添加一个会躲鼠标的可爱小幽灵,现在还能与DeepSeek对话!
// ==UserScript== // @name 超级调皮小幽灵 (DeepSeek版) // @namespace http://tampermonkey.net/ // @version 3.1 // @description 在页面上添加一个会躲鼠标的可爱小幽灵,现在还能与DeepSeek对话! // @author Coding Master // @match http://*/* // @match https://*/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_xmlhttpRequest // @run-at document-idle // @license MIT // ==/UserScript== (function() { 'use strict'; // 加载保存的设置 const savedSettings = GM_getValue('ghostSettings', { ghostColor: '#f0f0ff', eyeColor: '#64e3ff', size: 1, speed: 1, sensitivity: 120, autoHide: false, hideDuration: 30, showDuration: 60, showSpeech: true, enableDeepSeek: true, deepSeekAPIKey: '', deepSeekModel: 'deepseek-chat' }); // 创建设置面板 function createSettingsPanel() { const panel = document.createElement('div'); panel.id = 'ghost-settings-panel'; panel.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.2); z-index: 1000001; display: none; width: 350px; max-width: 90%; font-family: Arial, sans-serif; `; panel.innerHTML = ` <h2 style="margin-top: 0; color: #333;">幽灵设置</h2> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">幽灵颜色:</label> <input type="color" id="ghost-color" value="${savedSettings.ghostColor}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">眼睛颜色:</label> <input type="color" id="eye-color" value="${savedSettings.eyeColor}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">大小: ${savedSettings.size}x</label> <input type="range" id="ghost-size" min="0.5" max="2" step="0.1" value="${savedSettings.size}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">速度: ${savedSettings.speed}x</label> <input type="range" id="ghost-speed" min="0.5" max="2" step="0.1" value="${savedSettings.speed}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">敏感度: ${savedSettings.sensitivity}px</label> <input type="range" id="ghost-sensitivity" min="80" max="200" step="10" value="${savedSettings.sensitivity}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: flex; align-items: center;"> <input type="checkbox" id="ghost-auto-hide" ${savedSettings.autoHide ? 'checked' : ''} style="margin-right: 8px;"> 自动隐藏 </label> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">隐藏时长: ${savedSettings.hideDuration}秒</label> <input type="range" id="ghost-hide-duration" min="10" max="120" step="5" value="${savedSettings.hideDuration}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: block; margin-bottom: 5px; font-weight: bold;">显示时长: ${savedSettings.showDuration}秒</label> <input type="range" id="ghost-show-duration" min="10" max="120" step="5" value="${savedSettings.showDuration}" style="width: 100%;"> </div> <div style="margin-bottom: 15px;"> <label style="display: flex; align-items: center;"> <input type="checkbox" id="ghost-show-speech" ${savedSettings.showSpeech ? 'checked' : ''} style="margin-right: 8px;"> 显示对话气泡 </label> </div> <div style="margin-bottom: 15px; border-top: 1px solid #eee; padding-top: 15px;"> <label style="display: flex; align-items: center; margin-bottom: 10px;"> <input type="checkbox" id="enable-deepseek" ${savedSettings.enableDeepSeek ? 'checked' : ''} style="margin-right: 8px;"> <strong>启用DeepSeek对话</strong> </label> <div style="margin-bottom: 10px;"> <label style="display: block; margin-bottom: 5px; font-size: 13px;">DeepSeek API Key:</label> <input type="password" id="deepseek-api-key" value="${savedSettings.deepSeekAPIKey}" style="width: 100%; padding: 6px; border: 1px solid #ddd; border-radius: 4px;"> </div> <div style="margin-bottom: 10px;"> <label style="display: block; margin-bottom: 5px; font-size: 13px;">模型:</label> <select id="deepseek-model" style="width: 100%; padding: 6px; border: 1px solid #ddd; border-radius: 4px;"> <option value="deepseek-chat" ${savedSettings.deepSeekModel === 'deepseek-chat' ? 'selected' : ''}>DeepSeek Chat</option> <option value="deepseek-coder" ${savedSettings.deepSeekModel === 'deepseek-coder' ? 'selected' : ''}>DeepSeek Coder</option> </select> </div> <div style="font-size: 12px; color: #666; margin-top: 5px;"> 提示: 按D键可与幽灵对话 </div> </div> <div style="display: flex; justify-content: space-between;"> <button id="save-settings" style="padding: 8px 16px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">保存</button> <button id="reset-settings" style="padding: 8px 16px; background: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;">重置</button> <button id="close-settings" style="padding: 8px 16px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">关闭</button> </div> `; document.body.appendChild(panel); return panel; } // 创建对话面板 function createChatPanel() { const panel = document.createElement('div'); panel.id = 'ghost-chat-panel'; panel.style.cssText = ` position: fixed; bottom: 20px; right: 20px; width: 300px; max-width: 90%; background: white; border-radius: 15px; box-shadow: 0 0 20px rgba(0,0,0,0.2); z-index: 1000000; display: none; flex-direction: column; font-family: Arial, sans-serif; overflow: hidden; `; panel.innerHTML = ` <div style="background: #f5f5f5; padding: 12px; border-bottom: 1px solid #ddd; display: flex; justify-content: space-between; align-items: center;"> <h3 style="margin: 0; font-size: 16px; color: #333;">与幽灵对话</h3> <button id="close-chat" style="background: none; border: none; font-size: 18px; cursor: pointer; color: #666;">×</button> </div> <div id="chat-messages" style="flex: 1; padding: 15px; height: 300px; overflow-y: auto; background: #fff;"> <div style="text-align: center; color: #666; font-size: 14px; margin-top: 20px;"> 幽灵正在等待你的消息... </div> </div> <div style="padding: 15px; border-top: 1px solid #eee; background: #f9f9f9;"> <textarea id="chat-input" placeholder="输入消息..." style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; resize: none; min-height: 60px; margin-bottom: 10px;"></textarea> <div style="display: flex; justify-content: space-between;"> <button id="send-message" style="padding: 8px 16px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">发送</button> <button id="clear-chat" style="padding: 8px 16px; background: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;">清空</button> </div> </div> `; document.body.appendChild(panel); return panel; } // 添加聊天消息 function addChatMessage(role, content) { const chatMessages = document.getElementById('chat-messages'); if (!chatMessages) return; // 如果第一条消息是占位文本,清除它 if (chatMessages.children.length === 1 && chatMessages.children[0].textContent === "幽灵正在等待你的消息...") { chatMessages.innerHTML = ''; } const messageDiv = document.createElement('div'); messageDiv.style.marginBottom = '15px'; if (role === 'user') { messageDiv.innerHTML = ` <div style="display: flex; justify-content: flex-end; margin-bottom: 5px;"> <div style="background: #e3f2fd; color: #333; padding: 10px; border-radius: 10px; max-width: 80%; word-wrap: break-word;"> ${content} </div> </div> `; } else { messageDiv.innerHTML = ` <div style="display: flex; align-items: flex-start; margin-bottom: 5px;"> <div style="width: 30px; height: 30px; background: #f0f0ff; border-radius: 50%; margin-right: 10px; flex-shrink: 0;"></div> <div style="background: #f5f5f5; color: #333; padding: 10px; border-radius: 10px; max-width: 80%; word-wrap: break-word;"> ${content} </div> </div> `; } chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; } // 与DeepSeek API交互 async function chatWithDeepSeek(message) { if (!savedSettings.enableDeepSeek || !savedSettings.deepSeekAPIKey) { return "DeepSeek功能未启用或API Key未设置"; } addChatMessage('user', message); // 显示正在输入状态 const chatMessages = document.getElementById('chat-messages'); const typingIndicator = document.createElement('div'); typingIndicator.innerHTML = ` <div style="display: flex; align-items: flex-start; margin-bottom: 5px;"> <div style="width: 30px; height: 30px; background: #f0f0ff; border-radius: 50%; margin-right: 10px; flex-shrink: 0;"></div> <div style="background: #f5f5f5; color: #333; padding: 10px; border-radius: 10px; max-width: 80%; word-wrap: break-word;"> <div class="typing-indicator"> <span></span> <span></span> <span></span> </div> </div> </div> `; chatMessages.appendChild(typingIndicator); chatMessages.scrollTop = chatMessages.scrollHeight; // 添加打字动画样式 const style = document.createElement('style'); style.textContent = ` .typing-indicator { display: inline-flex; align-items: center; height: 20px; } .typing-indicator span { width: 6px; height: 6px; margin: 0 2px; background-color: #666; border-radius: 50%; display: inline-block; opacity: 0.4; } .typing-indicator span:nth-child(1) { animation: typing 1s infinite; } .typing-indicator span:nth-child(2) { animation: typing 1s infinite 0.2s; } .typing-indicator span:nth-child(3) { animation: typing 1s infinite 0.4s; } @keyframes typing { 0% { opacity: 0.4; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } 100% { opacity: 0.4; transform: translateY(0); } } `; document.head.appendChild(style); try { const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: "https://api.deepseek.com/v1/chat/completions", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${savedSettings.deepSeekAPIKey}` }, data: JSON.stringify({ model: savedSettings.deepSeekModel, messages: [ { role: "system", content: "你是一个调皮的网页小幽灵,喜欢开玩笑和恶作剧。用可爱、幽默的语气回答用户的问题,偶尔可以加入幽灵相关的双关语或玩笑。保持回答简洁,最多2-3句话。" }, { role: "user", content: message } ], temperature: 0.7, max_tokens: 150 }), onload: resolve, onerror: reject }); }); const data = JSON.parse(response.responseText); const reply = data.choices[0].message.content; // 移除正在输入状态 chatMessages.removeChild(typingIndicator); document.head.removeChild(style); addChatMessage('assistant', reply); // 如果气泡可见,也显示简短回复 if (savedSettings.showSpeech && document.getElementById('ghost-chat-panel').style.display !== 'block') { const shortReply = reply.length > 30 ? reply.substring(0, 30) + '...' : reply; showSpeechBubble(shortReply); } return reply; } catch (error) { console.error("DeepSeek API错误:", error); // 移除正在输入状态 chatMessages.removeChild(typingIndicator); document.head.removeChild(style); const errorMsg = "哎呀,幽灵网络出问题了!稍后再试吧~"; addChatMessage('assistant', errorMsg); if (savedSettings.showSpeech) { showSpeechBubble(errorMsg); } return errorMsg; } } // 注册菜单命令 GM_registerMenuCommand('幽灵设置', function() { const panel = document.getElementById('ghost-settings-panel') || createSettingsPanel(); panel.style.display = 'block'; }); // 创建幽灵元素 function createGhost() { const ghost = document.createElement('div'); ghost.id = 'playful-ghost'; ghost.style.cssText = ` position: fixed; width: ${80 * savedSettings.size}px; height: ${100 * savedSettings.size}px; cursor: pointer; z-index: 999999; transition: transform 0.3s ease, opacity 0.5s; user-select: none; display: none; `; ghost.innerHTML = ` <div class="ghost-container" style="position: relative; width: 100%; height: 100%;"> <div class="ghost-body" style="position: absolute; top: 0; left: 0; width: 100%; height: ${80 * savedSettings.size}px; background: ${savedSettings.ghostColor}; border-radius: 50% 50% 50% 50%; box-shadow: 0 0 ${15 * savedSettings.size}px rgba(255,255,255,0.5);"></div> <div class="ghost-eyes" style="position: absolute; top: ${35 * savedSettings.size}px; display: flex; justify-content: space-between; width: 100%; padding: 0 ${15 * savedSettings.size}px; transition: all 0.3s ease;"> <div class="eye left-eye" style="width: ${16 * savedSettings.size}px; height: ${22 * savedSettings.size}px; background: ${savedSettings.eyeColor}; border-radius: 50%; box-shadow: 0 0 ${8 * savedSettings.size}px rgba(100,227,255,0.8);"></div> <div class="eye right-eye" style="width: ${16 * savedSettings.size}px; height: ${22 * savedSettings.size}px; background: ${savedSettings.eyeColor}; border-radius: 50%; box-shadow: 0 0 ${8 * savedSettings.size}px rgba(100,227,255,0.8);"></div> </div> <div class="ghost-mouth" style="position: absolute; top: ${60 * savedSettings.size}px; left: 50%; transform: translateX(-50%); width: ${30 * savedSettings.size}px; height: ${12 * savedSettings.size}px; border-radius: 0 0 ${10 * savedSettings.size}px ${10 * savedSettings.size}px; background: ${savedSettings.eyeColor}; transition: all 0.3s ease;"></div> <div class="ghost-bottom" style="position: absolute; bottom: 0; width: 100%; height: ${30 * savedSettings.size}px; display: flex;"> <div style="flex: 1; height: 100%; background: ${savedSettings.ghostColor}; border-radius: 0 0 0 ${15 * savedSettings.size}px;"></div> <div style="flex: 1; height: 100%; background: ${savedSettings.ghostColor};"></div> <div style="flex: 1; height: 100%; background: ${savedSettings.ghostColor};"></div> <div style="flex: 1; height: 100%; background: ${savedSettings.ghostColor};"></div> <div style="flex: 1; height: 100%; background: ${savedSettings.ghostColor}; border-radius: 0 0 ${15 * savedSettings.size}px 0;"></div> </div> <div class="speech-bubble" style="position: absolute; left: 50%; top: -${80 * savedSettings.size}px; transform: translateX(-50%); background: white; color: #333; padding: ${8 * savedSettings.size}px ${12 * savedSettings.size}px; border-radius: ${20 * savedSettings.size}px; font-size: ${14 * savedSettings.size}px; width: max-content; max-width: ${200 * savedSettings.size}px; text-align: center; box-shadow: 0 ${2 * savedSettings.size}px ${10 * savedSettings.size}px rgba(0,0,0,0.1); display: none; z-index: 1000000; font-family: Arial, sans-serif;"> 👻 Boo! 点我试试! </div> <div class="ghost-hat" style="position: absolute; top: -${20 * savedSettings.size}px; left: 50%; transform: translateX(-50%); width: ${60 * savedSettings.size}px; height: ${20 * savedSettings.size}px; background: #FF5722; border-radius: ${5 * savedSettings.size}px ${5 * savedSettings.size}px 0 0; display: none;"></div> <div class="ghost-accessory" style="position: absolute; top: ${20 * savedSettings.size}px; right: ${10 * savedSettings.size}px; width: ${20 * savedSettings.size}px; height: ${20 * savedSettings.size}px; background: #FFC107; border-radius: 50%; display: none;"></div> </div> `; document.body.appendChild(ghost); return ghost; } // 初始化幽灵 const ghost = createGhost(); ghost.style.display = 'block'; ghost.style.left = '100px'; ghost.style.top = '100px'; // 存储幽灵状态 const ghostState = { posX: 100, posY: 100, velX: 0.8 * savedSettings.speed, velY: 0.8 * savedSettings.speed, rotation: 0, isHiding: false, emotion: 'normal', // normal, scared, happy, angry lastMouseX: 0, lastMouseY: 0, sensitivity: savedSettings.sensitivity, isFollowing: false, isDragging: false, dragOffsetX: 0, dragOffsetY: 0, lastHideTime: 0, lastShowTime: Date.now(), accessories: { hat: false, bowtie: false, glasses: false }, mood: 'playful', // playful, sleepy, excited currentAnimation: null, isChatting: false }; // 可说的话 const ghostPhrases = [ "👻 Boo! 我抓住你了!", "幽灵需要抱抱~", "网页浏览太孤单?", "哈!想戳我?", "别跑,一起玩嘛!", "幽灵也要交朋友!", "偷偷告诉你个秘密...", "哇!你鼠标跑好快!", "我飘呀飘~", "小心,我可能会消失!", "网页里有幽灵出没👻", "一起在网上冲浪吗?", "按F键切换跟随模式", "空格键让我消失/出现", "拖拽我可以移动我哦", "右键点击我有惊喜!", "我有点困了...zzZ", "今天心情特别好!", "别惹我生气哦!", "看看我的新帽子!", "我是不是很时尚?", "按D键可以和我聊天!", "我是AI幽灵,聪明着呢!" ]; // 改变幽灵表情 function setGhostEmotion(emotion) { if (ghostState.isHiding) return; ghostState.emotion = emotion; const eyes = ghost.querySelector('.ghost-eyes'); const mouth = ghost.querySelector('.ghost-mouth'); switch(emotion) { case 'scared': eyes.style.transform = 'translateY(5px)'; mouth.style.height = `${24 * savedSettings.size}px`; mouth.style.top = `${50 * savedSettings.size}px`; mouth.style.borderRadius = '50%'; break; case 'happy': eyes.style.transform = 'translateY(-4px) scale(0.9)'; mouth.style.height = `${8 * savedSettings.size}px`; mouth.style.top = `${62 * savedSettings.size}px`; mouth.style.width = `${40 * savedSettings.size}px`; mouth.style.borderRadius = `0 0 ${15 * savedSettings.size}px ${15 * savedSettings.size}px`; break; case 'angry': eyes.style.transform = 'translateY(2px)'; eyes.querySelector('.left-eye').style.transform = 'rotate(-10deg)'; eyes.querySelector('.right-eye').style.transform = 'rotate(10deg)'; mouth.style.height = `${6 * savedSettings.size}px`; mouth.style.top = `${65 * savedSettings.size}px`; mouth.style.width = `${40 * savedSettings.size}px`; mouth.style.borderRadius = '0'; break; case 'sleepy': eyes.style.transform = 'translateY(5px)'; eyes.querySelector('.left-eye').style.height = `${6 * savedSettings.size}px`; eyes.querySelector('.right-eye').style.height = `${6 * savedSettings.size}px`; mouth.style.height = `${4 * savedSettings.size}px`; mouth.style.top = `${65 * savedSettings.size}px`; mouth.style.width = `${30 * savedSettings.size}px`; mouth.style.borderRadius = '0'; break; default: // normal eyes.style.transform = ''; if (eyes.querySelector('.left-eye').style.transform) { eyes.querySelector('.left-eye').style.transform = ''; eyes.querySelector('.right-eye').style.transform = ''; } if (eyes.querySelector('.left-eye').style.height) { eyes.querySelector('.left-eye').style.height = `${22 * savedSettings.size}px`; eyes.querySelector('.right-eye').style.height = `${22 * savedSettings.size}px`; } mouth.style.height = `${12 * savedSettings.size}px`; mouth.style.top = `${60 * savedSettings.size}px`; mouth.style.width = `${30 * savedSettings.size}px`; mouth.style.borderRadius = `0 0 ${10 * savedSettings.size}px ${10 * savedSettings.size}px`; } } // 改变幽灵心情 function setGhostMood(mood) { ghostState.mood = mood; switch(mood) { case 'sleepy': setGhostEmotion('sleepy'); ghostState.velX *= 0.5; ghostState.velY *= 0.5; if (savedSettings.showSpeech) showSpeechBubble("我有点困了...zzZ"); break; case 'excited': setGhostEmotion('happy'); ghostState.velX *= 1.5; ghostState.velY *= 1.5; if (savedSettings.showSpeech) showSpeechBubble("今天心情特别好!"); break; default: // playful setGhostEmotion('normal'); } } // 显示说话气泡 function showSpeechBubble(text) { if (!savedSettings.showSpeech) return; const bubble = ghost.querySelector('.speech-bubble'); if (!bubble) return; bubble.textContent = text; bubble.style.display = 'block'; bubble.style.animation = 'fadeInUp 0.5s ease'; // 应用动画关键帧 const style = document.createElement('style'); style.textContent = ` @keyframes fadeInUp { 0% { opacity: 0; transform: translateX(-50%) translateY(10px); } 100% { opacity: 1; transform: translateX(-50%) translateY(0); } } `; document.head.appendChild(style); // 自动隐藏 setTimeout(() => { bubble.style.animation = 'fadeOut 0.5s ease'; // 添加淡出动画 const fadeOutStyle = document.createElement('style'); fadeOutStyle.textContent = ` @keyframes fadeOut { 0% { opacity: 1; transform: translateX(-50%) translateY(0); } 100% { opacity: 0; transform: translateX(-50%) translateY(-10px); } } `; document.head.appendChild(fadeOutStyle); setTimeout(() => { bubble.style.display = 'none'; document.head.removeChild(fadeOutStyle); }, 500); }, 3000); } // 幽灵隐身/显形 function toggleGhostVisibility() { if (ghostState.isHiding) { // 逐渐显现 ghost.style.opacity = '0'; ghost.style.display = 'block'; let opacity = 0; const fadeIn = setInterval(() => { opacity += 0.05; ghost.style.opacity = opacity; if (opacity >= 1) { clearInterval(fadeIn); ghostState.isHiding = false; ghostState.lastShowTime = Date.now(); } }, 30); // 随机新位置出现 ghostState.posX = 50 + Math.random() * (window.innerWidth - 100); ghostState.posY = 50 + Math.random() * (window.innerHeight - 150); // 显示欢迎消息 if (savedSettings.showSpeech) { setTimeout(() => { showSpeechBubble("我回来啦!"); }, 1000); } } else { // 逐渐消失 let opacity = 1; const fadeOut = setInterval(() => { opacity -= 0.05; ghost.style.opacity = opacity; if (opacity <= 0) { clearInterval(fadeOut); ghost.style.display = 'none'; ghostState.isHiding = true; ghostState.lastHideTime = Date.now(); } }, 30); // 显示再见消息 if (savedSettings.showSpeech) { showSpeechBubble("幽灵要躲起来啦!"); } } } // 切换配件显示 function toggleAccessory(accessory, show) { const element = ghost.querySelector(`.ghost-${accessory}`); if (element) { element.style.display = show ? 'block' : 'none'; ghostState.accessories[accessory] = show; } } // 随机切换心情 function randomMoodChange() { const moods = ['playful', 'sleepy', 'excited']; const randomMood = moods[Math.floor(Math.random() * moods.length)]; setGhostMood(randomMood); // 随机切换配件 if (Math.random() < 0.3) { toggleAccessory('hat', Math.random() > 0.5); } if (Math.random() < 0.3) { toggleAccessory('accessory', Math.random() > 0.5); } } // 移动幽灵 function moveGhost() { if (ghostState.isHiding) { // 如果幽灵正在隐藏,随机决定是否重新出现 if (savedSettings.autoHide && Date.now() - ghostState.lastHideTime > savedSettings.hideDuration * 1000) { toggleGhostVisibility(); } requestAnimationFrame(moveGhost); return; } // 自动隐藏检查 if (savedSettings.autoHide && Date.now() - ghostState.lastShowTime > savedSettings.showDuration * 1000) { toggleGhostVisibility(); requestAnimationFrame(moveGhost); return; } // 随机改变心情 if (Math.random() < 0.001) { randomMoodChange(); } const screenWidth = window.innerWidth; const screenHeight = window.innerHeight; // 在边界反弹 if (ghostState.posX < 40 || ghostState.posX > screenWidth - 40) { ghostState.velX *= -1; // 改变表情为惊讶 setGhostEmotion('scared'); setTimeout(() => setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'), 500); } if (ghostState.posY < 40 || ghostState.posY > screenHeight - 120) { ghostState.velY *= -1; setGhostEmotion('scared'); setTimeout(() => setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'), 500); } // 随机改变方向 if (Math.random() < 0.02) { ghostState.velX += (Math.random() - 0.5) * 0.8 * savedSettings.speed; ghostState.velY += (Math.random() - 0.5) * 0.8 * savedSettings.speed; // 限制速度 const speed = Math.sqrt(ghostState.velX * ghostState.velX + ghostState.velY * ghostState.velY); const maxSpeed = 1.5 * savedSettings.speed * (ghostState.mood === 'excited' ? 1.5 : 1); if (speed > maxSpeed) { ghostState.velX *= maxSpeed / speed; ghostState.velY *= maxSpeed / speed; } // 偶尔说话 if (Math.random() < 0.3 && savedSettings.showSpeech) { const randomPhrase = ghostPhrases[Math.floor(Math.random() * ghostPhrases.length)]; showSpeechBubble(randomPhrase); } } // 更新位置 ghostState.posX += ghostState.velX; ghostState.posY += ghostState.velY; // 应用位置 ghost.style.left = `${ghostState.posX}px`; ghost.style.top = `${ghostState.posY}px`; // 基于移动方向轻微旋转 ghostState.rotation = Math.atan2(ghostState.velY, ghostState.velX) * 5; ghost.style.transform = `rotate(${ghostState.rotation}deg)`; requestAnimationFrame(moveGhost); } // 鼠标移动事件处理 function handleMouseMove(e) { ghostState.lastMouseX = e.clientX; ghostState.lastMouseY = e.clientY; if (ghostState.isDragging) { ghostState.posX = e.clientX - ghostState.dragOffsetX; ghostState.posY = e.clientY - ghostState.dragOffsetY; return; } // 计算幽灵与鼠标的距离 const dx = ghostState.posX - e.clientX; const dy = ghostState.posY - e.clientY; const distance = Math.sqrt(dx * dx + dy * dy); // 如果鼠标在幽灵附近,幽灵会逃开 if (distance < ghostState.sensitivity && !ghostState.isFollowing) { const angle = Math.atan2(dy, dx); const force = (ghostState.sensitivity - distance) / ghostState.sensitivity * 1.5 * savedSettings.speed; ghostState.velX += Math.cos(angle) * force * 0.2; ghostState.velY += Math.sin(angle) * force * 0.2; // 限制速度 const speed = Math.sqrt(ghostState.velX * ghostState.velX + ghostState.velY * ghostState.velY); const maxSpeed = 3 * savedSettings.speed; if (speed > maxSpeed) { ghostState.velX *= maxSpeed / speed; ghostState.velY *= maxSpeed / speed; } // 改变表情为害怕 if (ghostState.mood !== 'sleepy') { setGhostEmotion('scared'); } } else if (ghostState.emotion === 'scared' && ghostState.mood !== 'sleepy') { // 鼠标离开后恢复表情 setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'); } } // 创建粒子效果 function createParticles(x, y, color) { for (let i = 0; i < 15; i++) { const particle = document.createElement('div'); particle.className = 'particle'; particle.style.cssText = ` position: fixed; width: ${Math.random() * 10 + 5}px; height: ${Math.random() * 10 + 5}px; background: ${color || (i % 3 === 0 ? savedSettings.eyeColor : i % 3 === 1 ? '#5e98f7' : savedSettings.ghostColor)}; border-radius: 50%; left: ${x}px; top: ${y}px; pointer-events: none; z-index: 999998; box-shadow: 0 0 6px ${i % 3 === 0 ? 'rgba(100,227,255,0.8)' : 'rgba(94,152,247,0.8)'}; `; document.body.appendChild(particle); // 粒子动画 const velX = (Math.random() - 0.5) * 10; const velY = (Math.random() - 0.7) * 8; const startTime = Date.now(); function animateParticle() { const elapsed = Date.now() - startTime; if (elapsed > 1000) { particle.remove(); return; } const progress = elapsed / 1000; const ease = 1 - Math.pow(1 - progress, 2); particle.style.left = `${x + velX * elapsed / 20}px`; particle.style.top = `${y + velY * elapsed / 20 - 0.5 * 0.2 * elapsed * elapsed / 100}px`; particle.style.opacity = `${1 - progress}`; particle.style.transform = `scale(${1 - progress * 0.5})`; requestAnimationFrame(animateParticle); } animateParticle(); } } // 创建心形效果 function createHearts(x, y) { for (let i = 0; i < 5; i++) { const heart = document.createElement('div'); heart.className = 'heart'; heart.innerHTML = '❤️'; heart.style.cssText = ` position: fixed; font-size: ${20 + Math.random() * 10}px; left: ${x}px; top: ${y}px; pointer-events: none; z-index: 999998; transform: translate(-50%, -50%); opacity: 0.8; `; document.body.appendChild(heart); // 心形动画 const angle = Math.random() * Math.PI * 2; const velocity = 1 + Math.random() * 2; const startTime = Date.now(); function animateHeart() { const elapsed = Date.now() - startTime; if (elapsed > 2000) { heart.remove(); return; } const progress = elapsed / 2000; heart.style.left = `${x + Math.cos(angle) * velocity * elapsed / 2}px`; heart.style.top = `${y - velocity * elapsed / 2 - 0.5 * 0.1 * elapsed * elapsed / 100}px`; heart.style.opacity = `${0.8 * (1 - progress)}`; heart.style.transform = `translate(-50%, -50%) scale(${1 + progress})`; requestAnimationFrame(animateHeart); } animateHeart(); } } // 幽灵点击事件 ghost.addEventListener('click', function(e) { if (e.button === 2) return; // 忽略右键 createParticles(e.clientX, e.clientY); setGhostEmotion('happy'); setTimeout(() => setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'), 1000); // 说话泡泡 if (savedSettings.showSpeech) { const randomPhrase = ghostPhrases[Math.floor(Math.random() * ghostPhrases.length)]; showSpeechBubble(randomPhrase); } // 点击后幽灵会瞬间跳跃到新位置 ghostState.posX = 50 + Math.random() * (window.innerWidth - 100); ghostState.posY = 50 + Math.random() * (window.innerHeight - 150); }); // 幽灵右键点击事件 ghost.addEventListener('contextmenu', function(e) { e.preventDefault(); createHearts(e.clientX, e.clientY); setGhostEmotion('happy'); setTimeout(() => setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'), 1000); if (savedSettings.showSpeech) { showSpeechBubble("谢谢你喜欢我!❤️"); } }); // 幽灵鼠标悬停事件 ghost.addEventListener('mouseenter', function() { if (ghostState.mood !== 'sleepy') { setGhostEmotion('happy'); } // 显示引导消息 if (Math.random() < 0.3 && savedSettings.showSpeech) { showSpeechBubble("点我可以传送!"); } }); ghost.addEventListener('mouseleave', function() { setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'); }); // 拖拽幽灵 ghost.addEventListener('mousedown', function(e) { if (e.button !== 0) return; // 只处理左键 ghostState.isDragging = true; ghostState.dragOffsetX = e.clientX - ghostState.posX; ghostState.dragOffsetY = e.clientY - ghostState.posY; ghostState.velX = 0; ghostState.velY = 0; // 改变表情为惊讶 setGhostEmotion('scared'); // 添加拖拽样式 ghost.style.cursor = 'grabbing'; ghost.style.transition = 'none'; }); document.addEventListener('mousemove', function(e) { if (ghostState.isDragging) { ghostState.posX = e.clientX - ghostState.dragOffsetX; ghostState.posY = e.clientY - ghostState.dragOffsetY; ghost.style.left = `${ghostState.posX}px`; ghost.style.top = `${ghostState.posY}px`; } }); document.addEventListener('mouseup', function() { if (ghostState.isDragging) { ghostState.isDragging = false; // 恢复样式 ghost.style.cursor = 'pointer'; ghost.style.transition = 'transform 0.3s ease, opacity 0.5s'; // 恢复表情 setTimeout(() => { setGhostEmotion(ghostState.mood === 'sleepy' ? 'sleepy' : 'normal'); }, 500); // 显示消息 if (savedSettings.showSpeech) { showSpeechBubble("哇!你移动了我!"); } } }); // 键盘控制 document.addEventListener('keydown', function(e) { // 按空格键让幽灵隐藏/出现 if (e.key === ' ') { toggleGhostVisibility(); } // 按F键切换跟随模式 else if (e.key === 'f' || e.key === 'F') { ghostState.isFollowing = !ghostState.isFollowing; if (savedSettings.showSpeech) { showSpeechBubble(ghostState.isFollowing ? "我来跟着你啦!" : "我想自由活动~"); } } // 按H键切换帽子 else if (e.key === 'h' || e.key === 'H') { const showHat = !ghostState.accessories.hat; toggleAccessory('hat', showHat); if (savedSettings.showSpeech) { showSpeechBubble(showHat ? "看看我的新帽子!" : "帽子不见了..."); } } // 按A键切换配件 else if (e.key === 'a' || e.key === 'A') { const showAccessory = !ghostState.accessories.accessory; toggleAccessory('accessory', showAccessory); if (savedSettings.showSpeech) { showSpeechBubble(showAccessory ? "我是不是很时尚?" : "配件不见了..."); } } // 按1键设置心情为活泼 else if (e.key === '1') { setGhostMood('playful'); } // 按2键设置心情为困倦 else if (e.key === '2') { setGhostMood('sleepy'); } // 按3键设置心情为兴奋 else if (e.key === '3') { setGhostMood('excited'); } // 按D键打开对话面板 else if (e.key === 'd' || e.key === 'D') { if (!savedSettings.enableDeepSeek) { if (savedSettings.showSpeech) { showSpeechBubble("DeepSeek功能未启用,请在设置中开启"); } return; } const chatPanel = document.getElementById('ghost-chat-panel') || createChatPanel(); chatPanel.style.display = 'flex'; document.getElementById('chat-input').focus(); } }); // 鼠标移动监听 document.addEventListener('mousemove', handleMouseMove); // 设置面板事件处理 const settingsPanel = createSettingsPanel(); document.getElementById('save-settings').addEventListener('click', function() { const newSettings = { ghostColor: document.getElementById('ghost-color').value, eyeColor: document.getElementById('eye-color').value, size: parseFloat(document.getElementById('ghost-size').value), speed: parseFloat(document.getElementById('ghost-speed').value), sensitivity: parseInt(document.getElementById('ghost-sensitivity').value), autoHide: document.getElementById('ghost-auto-hide').checked, hideDuration: parseInt(document.getElementById('ghost-hide-duration').value), showDuration: parseInt(document.getElementById('ghost-show-duration').value), showSpeech: document.getElementById('ghost-show-speech').checked, enableDeepSeek: document.getElementById('enable-deepseek').checked, deepSeekAPIKey: document.getElementById('deepseek-api-key').value, deepSeekModel: document.getElementById('deepseek-model').value }; GM_setValue('ghostSettings', newSettings); // 应用新设置 Object.assign(savedSettings, newSettings); // 更新幽灵外观 ghost.querySelector('.ghost-body').style.background = savedSettings.ghostColor; ghost.querySelector('.ghost-bottom div').style.background = savedSettings.ghostColor; ghost.querySelector('.eye').style.background = savedSettings.eyeColor; ghost.querySelector('.ghost-mouth').style.background = savedSettings.eyeColor; ghostState.sensitivity = savedSettings.sensitivity; ghostState.velX = 0.8 * savedSettings.speed; ghostState.velY = 0.8 * savedSettings.speed; // 调整大小 ghost.style.width = `${80 * savedSettings.size}px`; ghost.style.height = `${100 * savedSettings.size}px`; // 隐藏面板 settingsPanel.style.display = 'none'; if (savedSettings.showSpeech) { showSpeechBubble("设置已保存!"); } }); document.getElementById('reset-settings').addEventListener('click', function() { const defaultSettings = { ghostColor: '#f0f0ff', eyeColor: '#64e3ff', size: 1, speed: 1, sensitivity: 120, autoHide: false, hideDuration: 30, showDuration: 60, showSpeech: true, enableDeepSeek: true, deepSeekAPIKey: '', deepSeekModel: 'deepseek-chat' }; document.getElementById('ghost-color').value = defaultSettings.ghostColor; document.getElementById('eye-color').value = defaultSettings.eyeColor; document.getElementById('ghost-size').value = defaultSettings.size; document.getElementById('ghost-speed').value = defaultSettings.speed; document.getElementById('ghost-sensitivity').value = defaultSettings.sensitivity; document.getElementById('ghost-auto-hide').checked = defaultSettings.autoHide; document.getElementById('ghost-hide-duration').value = defaultSettings.hideDuration; document.getElementById('ghost-show-duration').value = defaultSettings.showDuration; document.getElementById('ghost-show-speech').checked = defaultSettings.showSpeech; document.getElementById('enable-deepseek').checked = defaultSettings.enableDeepSeek; document.getElementById('deepseek-api-key').value = defaultSettings.deepSeekAPIKey; document.getElementById('deepseek-model').value = defaultSettings.deepSeekModel; // 更新显示的标签 document.querySelector('label[for="ghost-size"]').textContent = `大小: ${defaultSettings.size}x`; document.querySelector('label[for="ghost-speed"]').textContent = `速度: ${defaultSettings.speed}x`; document.querySelector('label[for="ghost-sensitivity"]').textContent = `敏感度: ${defaultSettings.sensitivity}px`; document.querySelector('label[for="ghost-hide-duration"]').textContent = `隐藏时长: ${defaultSettings.hideDuration}秒`; document.querySelector('label[for="ghost-show-duration"]').textContent = `显示时长: ${defaultSettings.showDuration}秒`; }); document.getElementById('close-settings').addEventListener('click', function() { settingsPanel.style.display = 'none'; }); // 实时更新滑块标签 document.getElementById('ghost-size').addEventListener('input', function() { document.querySelector('label[for="ghost-size"]').textContent = `大小: ${this.value}x`; }); document.getElementById('ghost-speed').addEventListener('input', function() { document.querySelector('label[for="ghost-speed"]').textContent = `速度: ${this.value}x`; }); document.getElementById('ghost-sensitivity').addEventListener('input', function() { document.querySelector('label[for="ghost-sensitivity"]').textContent = `敏感度: ${this.value}px`; }); document.getElementById('ghost-hide-duration').addEventListener('input', function() { document.querySelector('label[for="ghost-hide-duration"]').textContent = `隐藏时长: ${this.value}秒`; }); document.getElementById('ghost-show-duration').addEventListener('input', function() { document.querySelector('label[for="ghost-show-duration"]').textContent = `显示时长: ${this.value}秒`; }); // 聊天面板事件处理 const chatPanel = createChatPanel(); document.getElementById('close-chat').addEventListener('click', function() { chatPanel.style.display = 'none'; }); document.getElementById('send-message').addEventListener('click', function() { const input = document.getElementById('chat-input'); const message = input.value.trim(); if (message) { chatWithDeepSeek(message); input.value = ''; } }); document.getElementById('clear-chat').addEventListener('click', function() { document.getElementById('chat-messages').innerHTML = ` <div style="text-align: center; color: #666; font-size: 14px; margin-top: 20px;"> 幽灵正在等待你的消息... </div> `; }); document.getElementById('chat-input').addEventListener('keydown', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); document.getElementById('send-message').click(); } }); // 启动幽灵动画 moveGhost(); // 窗口尺寸变化时重新定位 window.addEventListener('resize', function() { if (ghostState.posX > window.innerWidth - 40) { ghostState.posX = window.innerWidth - 40; } if (ghostState.posY > window.innerHeight - 120) { ghostState.posY = window.innerHeight - 120; } }); // 初始欢迎消息 setTimeout(() => { if (savedSettings.showSpeech) { showSpeechBubble("我是一只调皮的小幽灵 👻 (按Ctrl+Shift+G打开设置)"); } }, 2000); })();