// ==UserScript== // @name 猴子都会用的Bangumi文字渐变生成器 // @namespace https://github.com/wakabayu // @version 1.3 // @description 在 Bangumi 文本框工具栏中添加渐变生成器 // @include /^https?:\/\/(bgm\.tv|chii\.in|bangumi\.tv)\/.*/ // @grant none // @license wataame // @author wataame // @homepage https://bgm.tv/user/wataame // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 添加渐变按钮到所有工具栏 function addGradientButtonToAllToolbars() { document.querySelectorAll('.markItUpHeader').forEach(toolbar => { if (!toolbar.querySelector('.gradientButton')) { const gradientButton = document.createElement('a'); gradientButton.href = 'javascript:void(0);'; gradientButton.className = 'markItUpButton gradientButton'; gradientButton.title = '生成渐变文字'; gradientButton.innerHTML = '渐变'; toolbar.appendChild(gradientButton); const textarea = toolbar.closest('.markItUpContainer').querySelector('textarea'); gradientButton.addEventListener('click', () => { if (!textarea) return alert('找不到对应的文本区域'); const selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); if (!selectedText) return alert('请先选中需要应用渐变的文字'); openColorPicker(selectedText, textarea); }); } }); } // 生成颜色选择器 function openColorPicker(selectedText, textarea) { const colorPickerContainer = document.createElement('div'); colorPickerContainer.style = "position:fixed;top:50%;left:50%;transform:translate(-50%, -50%);background:#fff;padding:20px;border:1px solid #ccc;z-index:9999;box-shadow:0 0 10px rgba(0,0,0,0.1)"; colorPickerContainer.innerHTML = `



最近使用的方案:
`; document.body.appendChild(colorPickerContainer); loadGradientHistory(); document.querySelector('#generate').onclick = () => { const startColor = document.querySelector('#startColor').value; const endColor = document.querySelector('#endColor').value; const steps = parseInt(document.querySelector('#steps').value); if (isNaN(steps) || steps <= 0) return alert('请输入有效的步数'); const gradientText = generateGradientText(selectedText, startColor, endColor, steps); const beforeText = textarea.value.substring(0, textarea.selectionStart); const afterText = textarea.value.substring(textarea.selectionEnd); textarea.value = beforeText + gradientText + afterText; saveGradientHistory(startColor, endColor); document.body.removeChild(colorPickerContainer); }; document.querySelector('#cancel').onclick = () => document.body.removeChild(colorPickerContainer); } // 记录和加载最近的渐变方案 function saveGradientHistory(startColor, endColor) { const history = JSON.parse(localStorage.getItem('gradientHistory') || '[]'); const newEntry = { start: startColor, end: endColor }; // 检查是否已存在相同的方案,避免重复添加 if (!history.some(entry => entry.start === startColor && entry.end === endColor)) { history.unshift(newEntry); // 添加新方案到开头 if (history.length > 5) history.pop(); // 只保留最近 5 条 localStorage.setItem('gradientHistory', JSON.stringify(history)); } } function loadGradientHistory() { const historyContainer = document.querySelector('#historyContainer'); const history = JSON.parse(localStorage.getItem('gradientHistory') || '[]'); historyContainer.innerHTML = '最近方案:
'; history.forEach((entry, index) => { const historyButton = document.createElement('button'); historyButton.style = `background: linear-gradient(to right, ${entry.start}, ${entry.end}); border: none; color: #fff; padding: 5px; margin: 2px; cursor: pointer;`; historyButton.innerText = `方案 ${index + 1}`; historyButton.onclick = () => { document.querySelector('#startColor').value = entry.start; document.querySelector('#endColor').value = entry.end; }; historyContainer.appendChild(historyButton); }); } // 生成渐变文字,按步数分段添加颜色 function generateGradientText(text, startColor, endColor, steps) { const startRGB = hexToRgb(startColor), endRGB = hexToRgb(endColor); const segmentLength = Math.ceil(text.length / steps); let result = ''; for (let i = 0; i < steps; i++) { const ratio = i / (steps - 1); const r = clamp(Math.round(startRGB.r + ratio * (endRGB.r - startRGB.r))); const g = clamp(Math.round(startRGB.g + ratio * (endRGB.g - startRGB.g))); const b = clamp(Math.round(startRGB.b + ratio * (endRGB.b - startRGB.b))); const color = `#${rgbToHex(r)}${rgbToHex(g)}${rgbToHex(b)}`; // 获取当前段的文本内容并应用颜色 const segmentText = text.slice(i * segmentLength, (i + 1) * segmentLength); result += `[color=${color}]${segmentText}[/color]`; } return result; } // 将值限制在 0-255 范围内 const clamp = value => Math.max(0, Math.min(255, value)); // 十六进制转 RGB 和 RGB 转 十六进制 const hexToRgb = hex => ({ r: parseInt(hex.slice(1, 3), 16), g: parseInt(hex.slice(3, 5), 16), b: parseInt(hex.slice(5, 7), 16) }); const rgbToHex = value => value.toString(16).padStart(2, '0'); // 使用 MutationObserver 确保所有工具栏加载后添加按钮 new MutationObserver(() => addGradientButtonToAllToolbars()).observe(document.body, { childList: true, subtree: true }); })();