91 lines
3.8 KiB
JavaScript
91 lines
3.8 KiB
JavaScript
// ==UserScript==
|
||
// @name 抖音直播自动下翻 (可见性检测版)
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 1.4
|
||
// @description 只有当“直播中”标签在屏幕上可见时,才触发自动翻页
|
||
// @author Gemini
|
||
// @match *://*.douyin.com/*
|
||
// @grant none
|
||
// ==/UserScript==
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
// --- 1. 创建 UI 指示器 ---
|
||
const container = document.createElement('div');
|
||
container.style.cssText = 'position:fixed; bottom:60px; left:30px; display:flex; align-items:center; z-index:10001; pointer-events:none; font-family:sans-serif;';
|
||
|
||
const dot = document.createElement('div');
|
||
dot.style.cssText = 'width:12px; height:12px; background-color:#00ff00; border-radius:50%; box-shadow:0 0 10px #00ff00; transition:all 0.3s;';
|
||
|
||
const label = document.createElement('div');
|
||
label.innerText = '当前是直播间';
|
||
label.style.cssText = 'margin-left:10px; background:rgba(0,0,0,0.7); color:#00ff00; padding:4px 12px; border-radius:4px; font-size:12px; opacity:0; transition:0.3s; border:1px solid #00ff00;';
|
||
|
||
container.appendChild(dot);
|
||
container.appendChild(label);
|
||
document.body.appendChild(container);
|
||
|
||
let hasTriggeredForThisVideo = false;
|
||
|
||
// --- 2. 核心逻辑:判断元素是否真正可见 ---
|
||
const isElementVisible = (el) => {
|
||
if (!el) return false;
|
||
const rect = el.getBoundingClientRect();
|
||
// 1. 检查是否在视口范围内
|
||
// 2. 检查元素大小是否大于0(排除 display:none)
|
||
return (
|
||
rect.top >= 0 &&
|
||
rect.left >= 0 &&
|
||
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
||
rect.right <= (window.innerWidth || document.documentElement.clientWidth) &&
|
||
rect.width > 0 &&
|
||
rect.height > 0
|
||
);
|
||
};
|
||
|
||
const pressArrowDown = () => {
|
||
hasTriggeredForThisVideo = false;
|
||
const options = { key: 'ArrowDown', keyCode: 40, code: 'ArrowDown', which: 40, bubbles: true };
|
||
window.dispatchEvent(new KeyboardEvent('keydown', options));
|
||
document.dispatchEvent(new KeyboardEvent('keydown', options));
|
||
console.log('🚀 元素已可见,执行翻页');
|
||
};
|
||
|
||
const runDetection = () => {
|
||
// 使用 XPath 寻找目标元素
|
||
const xpath = "//div[contains(@class, 'semi-tag-content') and text()='直播中']";
|
||
const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||
|
||
// 如果元素存在 且 真正出现在屏幕上
|
||
if (element && isElementVisible(element)) {
|
||
// UI 变色并显示文字
|
||
label.style.opacity = '1';
|
||
dot.style.backgroundColor = '#ff4d4f';
|
||
dot.style.boxShadow = '0 0 15px #ff4d4f';
|
||
|
||
if (!hasTriggeredForThisVideo) {
|
||
hasTriggeredForThisVideo = true;
|
||
console.log( "检测到直播,执行按键翻页" );
|
||
// 发现可见直播,延迟 800ms 翻页,给人一点反应时间
|
||
setTimeout(pressArrowDown, 100);
|
||
}
|
||
} else {
|
||
// 恢复 UI 状态
|
||
label.style.opacity = '0';
|
||
dot.style.backgroundColor = '#00ff00';
|
||
dot.style.boxShadow = '0 0 10px #00ff00';
|
||
|
||
// 如果连元素都没了,说明已经翻过去了,重置触发开关
|
||
if (!element) {
|
||
hasTriggeredForThisVideo = false;
|
||
}
|
||
}
|
||
};
|
||
|
||
// --- 3. 监听 ---
|
||
// 抖音滑动比较快,我们结合 MutationObserver 和 高频轮询 确保不漏掉任何瞬间
|
||
setInterval(runDetection, 300); // 每 300ms 检查一次可见性
|
||
|
||
console.log('抖音直播可见性检测脚本注入成功');
|
||
})(); |