您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Make YouTube Player 480px Size
当前为
/* Resize the YouTube player to 480px size. Copyright (C) 2023 Runio This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/> */ // ==UserScript== // @name YouTube Sizer // @author Runio // @namespace namespace_runio // @version 1.44 // @description Make YouTube Player 480px Size // @match https://www.youtube.com/* // @match https://www.youtu.be/* // @exclude https://www.youtube.com/tv* // @exclude https://www.youtube.com/embed/* // @exclude https://www.youtube.com/live_chat* // @exclude https://www.youtube.com/shorts/* // @run-at document-end // @grant GM_setValue // @grant GM_getValue // @icon https://i.imgur.com/KJeLd60.png // @license GPL-3.0+ // @noframes // ==/UserScript== "use strict"; //================================================================== //Local Storage Functions if (window.frameElement) throw new Error("Stopped JavaScript."); function setPref(preference, new_value) { GM_setValue(preference, new_value); } function getPref(preference) { return GM_getValue(preference); } function initPref(preference, new_value) { let value = getPref(preference); if (value === null) { setPref(preference, new_value); value = new_value; } return value; } //================================================================== initPref("yt-resize", false); //================================================================== // Global Booleans var scrubBool = false; var prefDone = false; var resizeDone = false; //================================================================== // Global Variables var maxWidth = 480; // Max Width of Video var aspectRatio = 16 / 9; // Aspect Ratio var shortcutKey = "r"; // Shortcut Key var smallerCss = `#primary.ytd-watch-flexy:not([theater]):not([fullscreen]) { max-width: calc(${maxWidth}px * ${aspectRatio}) !important; }`; var ytresizeCss = `.ytp-big-mode .ytp-chrome-controls .ytp-resize-button { display: none !important; } .ytp-chrome-bottom { max-width: calc(100% - 24px);width: calc(100% - 24px) !important; }`; //================================================================== window.addEventListener("yt-navigate-start", () => { startScript(); }); window.addEventListener("yt-page-data-updated", () => { startScript(); }); //================================================================== // Start Script function startScript() { const isDocumentReady = ["complete", "loaded", "interactive"].includes(document.readyState); if (isDocumentReady) { startMethods(); } else { document.addEventListener("DOMContentLoaded", startMethods); } } //================================================================== function startMethods() { // Global Video Player Variables /* global ytd_video, movie_player, outer, video, ytd_flexy */ window.ytd_video = document.getElementById("ytd-player"); window.movie_player = document.getElementById("movie_player"); window.outer = document.getElementById("player-container-outer"); window.video = document.getElementsByTagName("video")[0]; window.ytd_flexy = document.getElementsByTagName("ytd-watch-flexy")[0]; if (!prefDone) { if (getPref("yt-resize")) { addCss(smallerCss, "small-player"); } autoResizeVideo(); addCss(ytresizeCss, "yt-css"); prefDone = true; } } //================================================================== //Scrubber Event Listener function getComputedTranslateXY(obj) { const transArr = []; if (!window.getComputedStyle) return; const style = getComputedStyle(obj), transform = style.transform || style.webkitTransform || style.mozTransform; let mat = transform.match(/^matrix3d\((.+)\)$/); if (mat) return parseFloat(mat[1].split(', ')[13]); mat = transform.match(/^matrix\((.+)\)$/); mat ? transArr.push(parseFloat(mat[1].split(', ')[4])) : 0; mat ? transArr.push(parseFloat(mat[1].split(', ')[5])) : 0; return transArr; } function scrubListener() { let elem = document.querySelector(".ytp-progress-bar-container > .ytp-progress-bar"); elem.addEventListener("timeupdate", function(elem) { let event = new CustomEvent('scrubber'); elem.dispatchEvent(event); }); elem.addEventListener("scrubber", function() { let scrub = document.querySelector(".ytp-progress-bar > .ytp-scrubber-container"); let progress = document.querySelector(".ytp-progress-list > .ytp-hover-progress"); let numericValue = window.getComputedStyle(progress, null).getPropertyValue('left').match(/\d+/); if (scrub) { if (Math.floor(getComputedTranslateXY(scrub)[0]) == parseInt(numericValue[0])) { scrubBool = true; } return (scrubBool); } else { return false; } }); } //================================================================== function isInViewport(video, element) { let rect = element.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom >= video.clientHeight && rect.right >= video.clientWidth ); } function isCentered(element1, element2) { let rect = element1.getBoundingClientRect(); let rect2 = element2.getBoundingClientRect(); let centered = { outer: rect.left + rect.width / 2, inner: rect2.left + rect2.width / 2, }; return ( Math.floor(centered.outer) == Math.floor(centered.inner) ); } function addCss(cssString, id) { const css = document.createElement('style'); css.type = "text/css"; css.id = id; css.innerHTML = cssString; document.head.appendChild(css); } function showResizeButtonTooltip(btn, show = true) { let tooltipTopOffset = 62; // Height Above The Button For The Tooltip const buttonRect = btn.getBoundingClientRect(); // Get Button Position const tooltipHorizontalCenter = buttonRect.left + buttonRect.width / 2; // Tooltip Horizontal Center const tooltipTop = buttonRect.top + buttonRect.height / 2 - tooltipTopOffset; // Tooltip Top const tooltip = document.getElementById("ytd-resize-tt") || createTooltip(); const tooltipText = tooltip.querySelector('#ytd-resize-tt-text'); if (show) { // Show tooltip.style.top = `${tooltipTop}px`; tooltipText.textContent = btn.getAttribute("aria-label"); tooltip.style.removeProperty("display"); const tooltipWidth = tooltip.getBoundingClientRect().width; tooltip.style.left = `${tooltipHorizontalCenter - tooltipWidth / 2}px`; btn.removeAttribute("title"); } else { // Hide tooltip.style.setProperty("display", "none"); tooltipText.textContent = ""; btn.setAttribute("title", btn.getAttribute("aria-label")); } function createTooltip() { const htmlPlayer = document.querySelector(".html5-video-player"); const tooltip = document.createElement("div"); const tooltipTextWrapper = document.createElement("div"); const tooltipText = document.createElement("span"); tooltip.setAttribute("class", "ytp-tooltip ytp-bottom"); tooltip.setAttribute("id", "ytd-resize-tt"); tooltip.style.setProperty("position", "fixed"); tooltipTextWrapper.setAttribute("class", "ytp-tooltip-text-wrapper"); tooltipText.setAttribute("class", "ytp-tooltip-text"); tooltipText.setAttribute("id", "ytd-resize-tt-text"); tooltip.appendChild(tooltipTextWrapper); tooltipTextWrapper.appendChild(tooltipText); htmlPlayer.appendChild(tooltip); return tooltip; } } /*Resize Video Container*/ function createResize() { let ytd = { height: movie_player.clientHeight, width: movie_player.clientWidth, }; if (ytd_video !== "undefined") { ytd_video.player_.setInternalSize(ytd.width, ytd.height); } return; } /*Resize Button Script*/ function buttonScript() { let splayer = document.getElementById("small-player"); if (document.head.contains(splayer)) { document.head.removeChild(splayer); } else { addCss(smallerCss, "small-player"); } } function setButton(btn, path) { var pathData = {}; var ariaLabel = ""; var title = ""; if (!getPref("yt-resize")) { pathData.d = "M 18 24 L 10 16 L 10 24 Z M 29 25 L 29 10.98 C 29 9.88 28.1 9 27 9 L 9 9 C 7.9 9 7 9.88 7 10.98 L 7 25 C 7 26.1 7.9 27 9 27 L 27 27 C 28.1 27 29 26.1 29 25 L 29 25 Z M 27 25.02 L 9 25.02 L 9 10.97 L 27 10.97 L 27 25.02 L 27 25.02 Z"; ariaLabel = `Resize View (${shortcutKey})`; title = `Resize View (${shortcutKey})`; } else { pathData.d = "M 26 20 L 26 12 L 18 12 Z M 29 25 L 29 10.98 C 29 9.88 28.1 9 27 9 L 9 9 C 7.9 9 7 9.88 7 10.98 L 7 25 C 7 26.1 7.9 27 9 27 L 27 27 C 28.1 27 29 26.1 29 25 L 29 25 Z M 27 25.02 L 9 25.02 L 9 10.97 L 27 10.97 L 27 25.02 L 27 25.02 Z"; ariaLabel = `Default View (${shortcutKey})`; title = `Default View (${shortcutKey})`; } path.setAttribute("d", pathData.d); btn.setAttribute("aria-label", ariaLabel); btn.setAttribute("title", title); } function createButton() { var abtn = document.getElementsByClassName("ytp-right-controls")[0]; var btn = document.createElement("button"); var path = document.createElement("path"); /*Start Create SVG*/ var svg = document.createElement("svg"); svg.setAttribute("height", "100%"); svg.setAttribute("version", "1.1"); svg.setAttribute("viewBox", "0 0 36 36"); svg.setAttribute("width", "100%"); var use = document.createElement("use"); use.setAttribute("class", "ytp-svg-shadow"); setButton(btn, path); // Decide Which Button path.setAttribute("fill", "#fff"); path.setAttribute("fill-rule", "evenodd"); svg.appendChild(use); svg.appendChild(path); const btnContent = svg.outerHTML; /*Finished Create SVG*/ btn.innerHTML = btnContent; btn.classList.add("ytp-resize-button", "ytp-button"); btn.setAttribute("id", "ytp-resize-button"); btn.setAttribute("data-tooltip-target-id", "ytp-resize-button"); abtn.insertBefore(btn, abtn.lastChild.previousSibling); document.addEventListener("keydown", function(e) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return; if (/^(?:input|textarea|select|button)$/i.test(e.target.tagName)) return; if (/(?:contenteditable-root)/i.test(e.target.id)) return; if (e.key == shortcutKey.toLowerCase() || e.key == shortcutKey.toUpperCase()) { e.preventDefault(); e.stopPropagation(); ytd_video.focus(); buttonScript(); } return; }); /*Tooltip Event Handlers*/ const showTooltip = (event) => { const isMouseOver = ["mouseover", "focus"].includes(event.type); showResizeButtonTooltip(btn, isMouseOver); }; btn.addEventListener("click", buttonScript); btn.addEventListener("mouseover", showTooltip); btn.addEventListener("mouseout", showTooltip); btn.addEventListener("focus", showTooltip); btn.addEventListener("blur", showTooltip); } /*Create Resize Button*/ function controlResize() { var buttonExists = document.getElementById("ytp-resize-button"); if (!buttonExists) { createButton(); } else { setButton(buttonExists, buttonExists.querySelector('path')); } } /*Viewport Observer*/ function viewObserver() { let resizeObserver = new ResizeObserver((entries) => { window.requestAnimationFrame(() => { if (!Array.isArray(entries) || !entries.length) { // Check Animation Frame return; } entries.forEach(entry => { const isInViewportYTD = isInViewport(video, ytd_flexy); const isCenteredMoviePlayer = isCentered(video, movie_player); const isInViewportMoviePlayer = isInViewport(video, movie_player); if (isInViewportYTD && !isCenteredMoviePlayer && (!isInViewportMoviePlayer || !scrubBool)) { const { height } = entry.contentRect; if (height !== maxWidth) { createResize(); } } }); }); entries.forEach(entry => console.log(`Player Size: ${entry.contentRect.height} x ${entry.contentRect.width}`)); }); // Observe The Given Element For Changes resizeObserver.observe(video); } /*Saves Size Setting*/ function sizeObserver() { const targetNode = document.head; const config = { attributes: true, childList: true, subtree: true }; const callback = function(mutationsList, observer) { for (let mutation of mutationsList) { if (mutation.removedNodes.length >= 1 && mutation.removedNodes[0].id == "small-player") { setPref("yt-resize", false); // Set Resize To False controlResize(); // Change Button Icon createResize(); // Resize Video Container } else if (mutation.addedNodes.length >= 1 && mutation.addedNodes[0].id == "small-player") { setPref("yt-resize", true); // Set Resize To True controlResize(); // Change Button Icon createResize(); // Resize Video Container } } }; const observer = new MutationObserver(callback); observer.observe(targetNode, config); } function autoResizeVideo() { if (outer !== "null") { scrubListener(); // Add Scrubber Listener sizeObserver(); // Size Observer viewObserver(); // Resize Observer window.addEventListener("yt-action", () => { // Adds Resize Button if (window.location.href.indexOf("youtube.com/watch") !== -1) { if (video !== "null" && !resizeDone) { controlResize(); resizeDone = true; } } }); video.addEventListener("canplay", () => { // Resize on video load setTimeout(function() { createResize(); }, 500); }); window.addEventListener("fullscreenchange", () => { if (!document.fullscreenElement) { // Check if leaving fullscreen createResize(); } }); } else { alert("player-container-outer not found"); } }