Greasy Fork

Greasy Fork is available in English.

视频网站自动网页全屏

支持哔哩哔哩、B站直播、腾讯视频、优酷视频、爱奇艺、芒果TV、搜狐视频、AcFun弹幕网播放页自动网页全屏,B站视频播放完成后自动退出网页全屏

当前为 2024-12-21 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         视频网站自动网页全屏
// @license      MIT
// @author       Feny
// @version      1.0.0
// @namespace    http://tampermonkey.net/
// @description  支持哔哩哔哩、B站直播、腾讯视频、优酷视频、爱奇艺、芒果TV、搜狐视频、AcFun弹幕网播放页自动网页全屏,B站视频播放完成后自动退出网页全屏
// @match      *://tv.sohu.com/v/*
// @match      *://www.mgtv.com/b/*
// @match      *://www.iqiyi.com/v_*
// @match      *://v.pptv.com/show/*
// @match      *://haokan.baidu.com/v*
// @match      *://v.youku.com/v_show/*
// @match      *://www.youtube.com/watch*
// @match      *://v.qq.com/x/page/*
// @match      *://v.qq.com/x/cover/*
// @match      *://v.qq.com/live/p/newtopic/*
// @match      *://www.acfun.cn/v/*
// @match      *://live.acfun.cn/live/*
// @match      *://www.acfun.cn/bangumi/*
// @match      *://live.bilibili.com/*
// @match      *://www.bilibili.com/list/*
// @match      *://www.bilibili.com/video/*
// @match      *://www.bilibili.com/festival/*
// @match      *://www.bilibili.com/cheese/play/*
// @match      *://www.bilibili.com/bangumi/play/*
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAqdJREFUWEftl91LFFEYxp/3jB9ESZjtSl51F1RUSgRCF/kHlF1IhiFhF65dqEQkBUErdJMStBukGwQre2NZUiCRqUiURkW65mIfqGUFsW6Ii0jY7p4Tc3Rqd5zaGVldAudynve8z28e3jMzh5Dmi1R/V0vQyRRWxgWG6x22SrcnOAhQcQIbwVtXba8y1EANSpS1xzJin5c/Dz+jRDPvGWoErwRw35zuh8ChpcXXFjbwi9k/WADA9viGgovGnxtFs6EmcApMvCdBA3oIIirl4N8NNQngmRYJiwTOE7EHHLERAmXFawQ6AdCQkRbjsZIMUvIFoV0HMSsEDjCgSK8tJqAHAEDAMWLKLOexx8tiVVDEhLLVQAtzRPcwKOUANSWCw1/rsBe6PcFz8dpfAdTFgtF+EmIvBG7pID7mZNl2zkVCFQbahzqHfYerddpNhFpdsnfqauzl8ZoEuO4JXdIKOefynnZlimxXhBbqjTZL/el8pzrAVjTGmKh12Bq1ddJs974abQDXfFMuAhQ6EodwDTHWAf6/BAoK8nD0cDEKtuVhyD+OzvvLXnyWJshyApedJ1F65M9n4tlAAF5fL168fGfJWCu2DDA61GpodLvjCdp8vfjyNWQJJGUAquvMzBzafD0yEc65KZCUAmiOo4FPEqS753VSiFUB0FxbPF244en6J8SqAoTD8zhYcjZ9AP6RCVRWNacHYPD5GJqudmBi8tvaAkxNBeUuuNv5NOkAqgUpm4FIJCrfA+r0z4bnTZmvCKCv+wrsts0JBg8fvZLGY28NfoqToFhOoOJ4CS40lMu2I28mpXFP37DpJ9YXWgZQG+Tm5mBL7qakA2aGakUAZhqbrVkH0BLoB34fzcyml5K6pd/yaicRlQlgV0q6mmwitMOpyfpVKfsFya4w73cz9xQAAAAASUVORK5CYII=
// ==/UserScript==

(function () {
    "use strict";

    // 针对:@match *://live.bilibili.com/*
    // 仅限像 live.bilibili.com/blanc/数字、live.bilibili.com/数字,才放行
    const host = location.host, href = location.href;
    const regExp = /live.bilibili.com\/(blanc\/)?\d+/;
    const isBiliLive = (host) => host === "live.bilibili.com";
    if (isBiliLive(host) && !regExp.test(href)) return;

    // 重写pushState方法
    const orig = history.pushState;
    history.pushState = function () {
        orig.apply(this, arguments);
        window.dispatchEvent(new Event("pushstate"));
    };

    // 重写replaceState方法
    const original = history.replaceState;
    history.replaceState = function () {
        original.apply(this, arguments);
        window.dispatchEvent(new Event("replaceState"));
    };

    const selector = {
        "live.bilibili.com": { webfull: "#businessContainerElement" },
        "live.acfun.cn": { full: ".fullscreen-screen", webfull: ".fullscreen-web", danmaku: ".danmaku-enabled" },
        "www.youtube.com": { full: ".ytp-fullscreen-button", webfull: ".ytp-size-button", next: ".ytp-next-button" },
        "tv.sohu.com": { full: ".x-fullscreen-btn", webfull: ".x-pagefs-btn", danmaku: ".tm-tmbtn", next: ".x-next-btn" },
        "haokan.baidu.com": { full: ".art-icon-fullscreen", webfull: ".art-control-fullscreenWeb", next: ".art-control-next" },
        "www.iqiyi.com": { full: ".iqp-btn-fullscreen", webfull: ".iqp-btn-webscreen", danmaku: "#barrage_switch", next: ".iqp-btn-next" },
        "www.mgtv.com": { full: ".fullscreenBtn i", webfull: ".webfullscreenBtn i", danmaku: "div[class*='danmuSwitch']", next: ".icon-next" },
        "v.qq.com": { full: ".txp_btn_fullscreen", webfull: "div[aria-label='网页全屏']", danmaku: ".barrage-switch", next: ".txp_btn_next_u" },
        "v.pptv.com": { full: ".w-zoom-container > div", webfull: ".w-expand-container > div", danmaku: ".w-barrage", next: ".w-next-container" },
        "www.acfun.cn": { full: ".fullscreen-screen", webfull: ".fullscreen-web", danmaku: ".danmaku-enabled", next: ".btn-next-part .control-btn" },
        "www.bilibili.com": { full: "div[aria-label='全屏']", webfull: "div[aria-label='网页全屏']", danmaku: ".bui-area", next: ".bpx-player-ctrl-next" },
        "v.youku.com": { full: "#fullscreen-icon", webfull: "#webfullscreen-icon", danmaku: "div[class*='switch-img_12hDa turn-']", next: ".kui-next-icon-0" },
    }

    const _q = (selector) => document.querySelector(selector);
    const dblclick = new MouseEvent("dblclick", { bubbles: true });
    const hotKeyHandle = (e) => {
        // 判断当前获得焦点的元素是否是输入框元素
        const tagName = document.activeElement.tagName;
        if (["INPUT", "TEXTAREA"].includes(tagName)) return;
        const key = e.key.toUpperCase();
        const elem = webfullscreen.getElement();
        if (key === "N") _q(selector[host]?.next)?.click(); // 下一个
        if (key === "P") isBiliLive(host) ? elem.dispatchEvent(dblclick) : elem.click(); // 网页全屏切换
        // 全屏切换
        if (key === "F") {
            if (!isBiliLive(host)) return _q(selector[host]?.full)?.click();
            const control = webfullscreen.getLiveControl();
            if (control) control[0].click();
        }
        // 弹幕开/关
        if (key === "D") {
            if (!isBiliLive(host)) return _q(selector[host]?.danmaku)?.click();
            const control = webfullscreen.getLiveControl();
            if (control) control[3].click();
        }
    }
    const webfullscreen = {
        init() {
            const observer = new MutationObserver(() => {
                const video = this.getVideo();
                const element = this.getElement();
                if (video) this.exitWebFull(video);
                if (element) this.fullScreen(element) && this.hotKey() && observer.disconnect();
            });
            observer.observe(document.body, { childList: true, subtree: true });
            setTimeout(() => observer.disconnect(), 30000); // 30秒后销毁
        },
        getVideo: () => _q("video"),
        getElement: () => _q(selector[host].webfull),
        fullScreen(element) {
            const video = this.getVideo();
            if (!video) return false;
            const w = video.offsetWidth;
            if (0 === w) return false; // 芒果TV会出现该问题
            if (window.innerWidth === w) return true;
            if (!isBiliLive(host)) return element.click() || true;
            // B站直播
            parent.scrollTo({ top: 100 }); // 解决iframe直播间,导航栏不隐藏问题
            element.dispatchEvent(dblclick); // 双击网页全屏
            localStorage.setItem("FULLSCREEN-GIFT-PANEL-SHOW", 0); // 关闭全屏礼物栏
            document.body.classList.add("hide-asida-area", "hide-aside-area"); // 关闭侧边聊天栏
            setTimeout(() => _q("#shop-popover-vm")?.remove(), 500); // 关闭购物“小橙车”提示
            let i = 0, intervalID = setInterval(() => { // 关闭推荐主播浮窗
                if (++i >= 5) clearInterval(intervalID);
                const popup = _q(".side-bar-popup-cntr");
                if (popup) popup.remove() & clearInterval(intervalID);
            }, 500);
            window.top?.livePlayer?.switchQuality("10000"); // 原画画质
            return true;
        },
        getLiveControl() { // 获取B站直播控制栏
            const video = this.getVideo();
            if (!video) return;
            function simulateMouseMove(x, y) {
                const event = new MouseEvent('mousemove', {
                    clientX: x,
                    clientY: y,
                    bubbles: true,
                    cancelable: true,
                });
                video.dispatchEvent(event);
            }
            // 模拟鼠标从左到右滑动,呼出控制栏
            for (let i = 0; i < video.offsetWidth; i += 100) {
                simulateMouseMove(i, video.offsetHeight / 2);
            }
            // 图标是从右到左:全屏、网页全屏、弹幕设置、弹幕开关、小窗模式
            // 集下标[0]获取到的是全屏图标
            return document.querySelectorAll("#web-player-controller-wrap-el .right-area .icon");
        },
        hotKey() {
            // 用parent,解决iframe直播间快捷键不起作用问题
            parent.removeEventListener("keydown", hotKeyHandle);
            parent.addEventListener("keydown", hotKeyHandle);
            return true;
        },
        exitWebFull(video) {
            // B站视频播放完成后自动退出网页全屏
            const reg = /bilibili.com\/video/;
            if (!reg.test(href)) return;
            video.addEventListener('ended', () => {
                if (window.innerWidth === video.offsetWidth) this.getElement().click();
                const cancel = _q(".bpx-player-ending-related-item-cancel"); // 取消连播 按钮
                if (cancel) cancel.click();
            });
        }
    };

    webfullscreen.init();
    window.addEventListener("pushstate", () => webfullscreen.init());
    window.addEventListener("replaceState", () => webfullscreen.init());
})();