// ==UserScript==
// @name 咪咕弹幕
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 咪咕弹幕。没有就给你搞一个呗,移动这个懒B!
// @icon https://www.miguvideo.com/favicon.ico
// @author IDCIM rogermmg@gmail.com
// @match https://www.miguvideo.com/p/live/*
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @downloadURL https://update.greasyfork.icu/scripts/501988/%E5%92%AA%E5%92%95%E5%BC%B9%E5%B9%95.user.js
// @updateURL https://update.greasyfork.icu/scripts/501988/%E5%92%AA%E5%92%95%E5%BC%B9%E5%B9%95.meta.js
// ==/UserScript==
(function() {
'use strict';
// 日志函数
function log(message) {
console.log('[咪咕弹幕脚本]', message);
}
// 默认设置
const defaultSettings = {
enabled: true,
speed: 15,
fontSize: 20,
topHalfOnly: true
};
// 获取设置
function getSettings() {
return {
enabled: GM_getValue('danmakuEnabled', defaultSettings.enabled),
speed: GM_getValue('danmakuSpeed', defaultSettings.speed),
fontSize: GM_getValue('danmakuFontSize', defaultSettings.fontSize),
topHalfOnly: GM_getValue('danmakuTopHalfOnly', defaultSettings.topHalfOnly)
};
}
// 保存设置
function saveSettings(settings) {
GM_setValue('danmakuEnabled', settings.enabled);
GM_setValue('danmakuSpeed', settings.speed);
GM_setValue('danmakuFontSize', settings.fontSize);
GM_setValue('danmakuTopHalfOnly', settings.topHalfOnly);
}
// 等待元素出现的函数
function waitForElement(selector, timeout = 1000) {
return new Promise((resolve, reject) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
resolve(document.querySelector(selector));
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
setTimeout(() => {
observer.disconnect();
reject(new Error(`Timeout waiting for ${selector}`));
}, timeout);
});
}
// 创建弹幕容器
function createDanmakuContainer(playerElement) {
const container = document.createElement('div');
container.id = 'danmaku-container';
container.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
z-index: 9999;
`;
playerElement.appendChild(container);
return container;
}
// 创建弹幕元素函数
function createDanmaku(avatar, name, text, settings) {
const danmaku = document.createElement('div');
danmaku.className = 'danmaku-item';
danmaku.style.cssText = `
position: absolute;
white-space: nowrap;
font-size: ${settings.fontSize}px;
color: #fff;
text-shadow: 1px 1px 2px #000;
display: flex;
align-items: center;
right: -100%;
transition: right ${settings.speed}s linear;
`;
danmaku.innerHTML = `
${name}
${text}
`;
const topPosition = settings.topHalfOnly ? `${Math.random() * 40}%` : `${Math.random() * 80}%`;
danmaku.style.top = topPosition;
return danmaku;
}
// 添加新弹幕函数
function addDanmaku(container, settings) {
if (!settings.enabled) return;
log('开始添加弹幕');
const items = document.querySelectorAll('.list-wrapper .list_item:not(.processed)');
log(`找到 ${items.length} 个列表项`);
items.forEach((item, index) => {
item.classList.add('processed'); // 标记已处理项
setTimeout(() => {
const avatarImg = item.querySelector('img');
const nameSpan = item.querySelector('.name');
const textSpan = item.querySelector('.text');
if (!avatarImg || !nameSpan || !textSpan) {
log('未找到必要的元素', item);
return;
}
const avatar = avatarImg.src;
const name = nameSpan.textContent.trim();
const text = textSpan.textContent.trim();
log(`创建弹幕: ${name} - ${text}`);
const danmaku = createDanmaku(avatar, name, text, settings);
container.appendChild(danmaku);
// 开始动画
setTimeout(() => {
danmaku.style.right = '100%';
}, 50);
// 动画结束后删除弹幕
danmaku.addEventListener('transitionend', () => {
danmaku.remove();
});
}, index * 1000); // 将每个弹幕的间隔时间改为 1 秒
});
}
// 创建设置面板
function createSettingsPanel(container, settings) {
const panel = document.createElement('div');
panel.id = 'danmaku-settings-panel';
panel.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
border-radius: 10px;
z-index: 10001;
display: none;
`;
panel.innerHTML = `