B站循环助手-自适应版

稳定可靠的AB点循环工具,适配最新B站页面结构

当前为 2025-02-21 提交的版本,查看 最新版本

// ==UserScript==
// @name         B站循环助手-自适应版
// @namespace    bilibili-replayer
// @version      1.22
// @description  稳定可靠的AB点循环工具,适配最新B站页面结构
// @author       dms
// @match        https://www.bilibili.com/video/BV*
// @match        https://www.bilibili.com/bangumi/play/ep*
// @match        https://www.bilibili.com/medialist/play/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        GM_notification
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';
    
    // [其他类的代码保持不变...]

    const createToolbar = () => {
        let retryCount = 0;
        const maxRetries = 30;

        const tryCreate = () => {
            const video = document.querySelector('#bilibili-player video');
            const controlBar = document.querySelector('.bpx-player-control-bottom');
            
            if (!video || !controlBar) {
                retryCount++;
                if (retryCount < maxRetries) {
                    setTimeout(tryCreate, 500);
                }
                return;
            }

            const controller = new VideoController(video);

            // 修改控制栏样式以支持flex布局
            controlBar.style.display = 'flex';
            controlBar.style.alignItems = 'center';
            controlBar.style.position = 'relative';

            // 获取或创建右侧控制区
            let rightControls = controlBar.querySelector('.bpx-player-control-right');
            if (!rightControls) {
                rightControls = document.createElement('div');
                rightControls.className = 'bpx-player-control-right';
                controlBar.appendChild(rightControls);
            }

            // 创建工具栏容器
            const toolbarbox = document.createElement('div');
            toolbarbox.className = 'ab-loop-toolbar';
            
            // 将工具栏插入到右侧控制区的开头
            if (rightControls.firstChild) {
                rightControls.insertBefore(toolbarbox, rightControls.firstChild);
            } else {
                rightControls.appendChild(toolbarbox);
            }

            // 创建自定义样式
            const style = document.createElement('style');
            style.textContent = `
                .ab-loop-toolbar {
                    display: flex;
                    align-items: center;
                    height: 100%;
                    margin-right: 10px;
                }
                .bpx-player-control-right {
                    display: flex;
                    align-items: center;
                }
                .tool-item {
                    padding: 0 6px;
                    margin: 0 1px;
                    height: 22px;
                    line-height: 22px;
                    color: #ffffff;
                    cursor: pointer;
                    opacity: 0.85;
                    transition: all 0.2s ease;
                    border-radius: 2px;
                    user-select: none;
                }
                .tool-button:hover {
                    opacity: 1;
                    background-color: rgba(255, 255, 255, 0.1);
                }
                .active-button {
                    background-color: #00a1d6 !important;
                    color: white !important;
                    opacity: 1 !important;
                }
                /* 全屏模式下的样式调整 */
                .bpx-player-container[data-screen="full"] .ab-loop-toolbar {
                    height: 32px;
                }
                .bpx-player-container[data-screen="full"] .tool-item {
                    height: 24px;
                    line-height: 24px;
                    font-size: 14px;
                }
            `;
            document.head.appendChild(style);

            // 创建按钮
            const pointA = Utils.createButton('起点', 'tool-item tool-button', toolbarbox);
            const toA = Utils.createButton('跳A', 'tool-item tool-button', toolbarbox);
            
            Utils.createButton('|', 'tool-item tool-text', toolbarbox);
            const pointB = Utils.createButton('终点', 'tool-item tool-button', toolbarbox);
            const toB = Utils.createButton('跳B', 'tool-item tool-button', toolbarbox);
            
            Utils.createButton('|', 'tool-item tool-text', toolbarbox);
            const Start = Utils.createButton('▶循环', 'tool-item tool-button', toolbarbox);

            controller.pointButtons = [pointA, pointB];

            // 事件监听
            pointA.addEventListener('click', () => {
                controller.setPoint(0, video.currentTime);
            });

            pointB.addEventListener('click', () => {
                controller.setPoint(1, video.currentTime);
            });

            Start.addEventListener('click', () => controller.startLoop(Start));
            toA.addEventListener('click', () => { video.currentTime = controller.points[0]; });
            toB.addEventListener('click', () => { video.currentTime = controller.points[1]; });

            // 全屏切换监听
            const observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    if (mutation.type === 'attributes' && mutation.attributeName === 'data-screen') {
                        // 可以在这里添加全屏切换时的额外处理逻辑
                    }
                });
            });

            const playerContainer = document.querySelector('.bpx-player-container');
            if (playerContainer) {
                observer.observe(playerContainer, {
                    attributes: true,
                    attributeFilter: ['data-screen']
                });
            }
        };

        tryCreate();
    };

    // 检查页面加载状态
    if (document.readyState === 'complete') {
        createToolbar();
    } else {
        window.addEventListener('load', createToolbar);
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址