// ==UserScript==
// @name Bangumi 渐变生成器
// @namespace https://github.com/wakabayu
// @version 1.1
// @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);
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;
document.body.removeChild(colorPickerContainer);
};
document.querySelector('#cancel').onclick = () => document.body.removeChild(colorPickerContainer);
}
// 生成渐变文字,按步数分段添加颜色
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 });
})();