// ==UserScript== // @name Bangumi 超合金快捷搜索 // @namespace https://bgm.tv/ // @version 1.0 // @description 在任意网站选中文本后,鼠标旁弹出 Bangumi(bgm.tv)快捷搜索浮窗 // @author Cuiqi // @match *://*/* // @grant none // @run-at document-end // ==/UserScript== (function () { 'use strict'; const SEARCH_URL = 'https://bgm.tv/subject_search/'; let popup = null; let selectedText = ''; let mouseX = 0; let mouseY = 0; // ==================== 样式注入 ==================== function injectStyles() { const style = document.createElement('style'); style.textContent = ` #bgm-quick-search-popup { position: fixed; z-index: 2147483647; display: none; align-items: center; gap: 6px; padding: 8px 14px; background: linear-gradient(135deg, #f09199 0%, #e5737b 100%); border-radius: 22px; box-shadow: 0 4px 16px rgba(240,145,153,0.45), 0 2px 6px rgba(0,0,0,0.18); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 13px; color: #fff; cursor: pointer; user-select: none; white-space: nowrap; pointer-events: auto; opacity: 0; transform: translateY(4px); transition: opacity 0.15s ease, transform 0.15s ease; } #bgm-quick-search-popup.show { opacity: 1; transform: translateY(0); } #bgm-quick-search-popup:hover { box-shadow: 0 6px 22px rgba(240,145,153,0.55), 0 2px 6px rgba(0,0,0,0.2); transform: translateY(-2px); } #bgm-quick-search-popup:active { transform: translateY(0) scale(0.96); } #bgm-quick-search-icon { width: 18px; height: 18px; flex-shrink: 0; } #bgm-quick-search-text { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.9; } #bgm-quick-search-label { font-weight: 600; letter-spacing: 0.3px; flex-shrink: 0; } `; document.head.appendChild(style); } // ==================== 创建浮窗 ==================== function createPopup() { if (popup) return; popup = document.createElement('div'); popup.id = 'bgm-quick-search-popup'; popup.innerHTML = ` 在 Bangumi 搜索 `; popup.addEventListener('click', doSearch); document.body.appendChild(popup); } // ==================== 搜索 ==================== function doSearch(e) { e.stopPropagation(); e.preventDefault(); if (!selectedText) return; var kw = selectedText.trim(); if (!kw) return; window.open(SEARCH_URL + encodeURIComponent(kw), '_blank', 'noopener,noreferrer'); hidePopup(); } // ==================== 鼠标追踪 ==================== function trackMouse(e) { mouseX = e.clientX; mouseY = e.clientY; } // ==================== 定位(position:fixed,相对于视口) ==================== function positionPopup() { if (!popup) return; // 临时显示以便测量尺寸 popup.style.visibility = 'hidden'; popup.style.display = 'flex'; var pw = popup.offsetWidth; var ph = popup.offsetHeight; popup.style.visibility = ''; // 弹窗默认出现在鼠标右下方 var left = mouseX + 12; var top = mouseY + 16; // 右边溢出 → 放鼠标左边 if (left + pw > window.innerWidth - 8) { left = mouseX - pw - 12; } // 下方溢出 → 放鼠标上方 if (top + ph > window.innerHeight - 8) { top = mouseY - ph - 12; } // 兜底不溢出屏幕 left = Math.max(8, Math.min(window.innerWidth - pw - 8, left)); top = Math.max(8, Math.min(window.innerHeight - ph - 8, top)); popup.style.left = left + 'px'; popup.style.top = top + 'px'; } // ==================== 显示 / 隐藏 ==================== function showPopup(text) { if (!popup) createPopup(); if (!text) { hidePopup(); return; } selectedText = text; var textEl = popup.querySelector('#bgm-quick-search-text'); if (textEl) { textEl.textContent = text.length > 30 ? '"' + text.slice(0, 30) + '…"' : '"' + text + '"'; textEl.title = text; } positionPopup(); // 双 rAF 等 layout 稳定再播动画 requestAnimationFrame(function () { requestAnimationFrame(function () { popup.classList.add('show'); }); }); } function hidePopup() { if (!popup) return; popup.classList.remove('show'); selectedText = ''; setTimeout(function () { if (!popup.classList.contains('show')) { popup.style.display = 'none'; } }, 160); } // ==================== 事件处理 ==================== function onMouseUp(e) { // 忽略弹窗自身点击 if (e.target.closest('#bgm-quick-search-popup')) return; mouseX = e.clientX; mouseY = e.clientY; // 小延迟等 selection 稳定 setTimeout(function () { var sel = window.getSelection(); if (!sel || sel.isCollapsed) { hidePopup(); return; } var text = sel.toString().trim(); if (!text || text.length > 500) { hidePopup(); return; } showPopup(text); }, 10); } function onClick(e) { if (!e.target.closest('#bgm-quick-search-popup')) { hidePopup(); } } function onKeyDown(e) { if (e.key === 'Escape') hidePopup(); if (e.key === 'B' && e.ctrlKey && e.shiftKey) { e.preventDefault(); var text = window.getSelection().toString().trim(); if (text && text.length <= 500) { window.open(SEARCH_URL + encodeURIComponent(text), '_blank', 'noopener,noreferrer'); } } } // ==================== 启动 ==================== function init() { if (!document.body) { setTimeout(init, 50); return; } injectStyles(); createPopup(); document.addEventListener('mouseup', onMouseUp, { passive: true }); document.addEventListener('mousemove', trackMouse, { passive: true }); document.addEventListener('click', onClick, { passive: true }); document.addEventListener('keydown', onKeyDown, { passive: false }); console.log('[BGM搜索] ✅ 脚本就绪 — 选中文字松手即可看到弹窗'); } if (document.body) { init(); } else { document.addEventListener('DOMContentLoaded', init); } })();