您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds media controls for Redgifs
// ==UserScript== // @name Redgifs media controls // @namespace http://tampermonkey.net/ // @version 2.0.0 // @description Adds media controls for Redgifs // @author You // @match https://www.redgifs.com/watch/* // @icon https://www.google.com/s2/favicons?sz=64&domain=redgifs.com // @license MIT // @grant none // ==/UserScript== /* jshint esversion: 6 */ (function() { "use strict"; console.info("Redgifs media controls initiated"); const SELECTORS = { MUTE_BUTTON: ".sound", QUALITY_BUTTON: ".gif-quality", PLAY_BUTTON: "video", SEARCH_BOX_ID: "global-search-input" }; var videoElement = getPlayerInSight(); function getPlayerInSight() { const element = document.fullscreenElement || Array.prototype.filter.call(document.querySelectorAll(".player"), isInViewport)[0]; console.log("ELEMENT IN SIGHT", element); return element || videoElement; } function videoPlayerRefresher() { // if video player isn't assigned, look for it again videoElement = videoElement || getPlayerInSight(); } function isMuted() { return (videoElement.querySelector(`${SELECTORS.MUTE_BUTTON} > div[class=label]`).innerText === "Off"); } function toggleSound(forceSoundState = false) { if (forceSoundState) { if (!isMuted()) { return; } } videoElement.querySelector(SELECTORS.MUTE_BUTTON)?.click(); } function toggleFullscreen() { if (document.fullscreen) { document.exitFullscreen(); } else { videoElement.requestFullscreen(); } } function getQuality() { return videoElement.querySelector(SELECTORS.QUALITY_BUTTON)?.classList[1]; } function toggleQuality(forceHDState = false) { const qualityButton = videoElement.querySelector(SELECTORS.QUALITY_BUTTON); if (forceHDState && qualityButton?.classList.contains("hd")) { return; } qualityButton?.click(); } function togglePlayState(forcePlayState) { const playerElement = videoElement.querySelector(SELECTORS.PLAY_BUTTON); if (forcePlayState === true) { playerElement.play(); return; } else if (forcePlayState === false) { playerElement.pause(); return; } playerElement.click(); } function seekVideo(time, isMarker=false, absolute=false) { const video = videoElement.querySelector("video"); if (absolute) { video.currentTime = Number(time); } else if (!isMarker) { video.currentTime = Math.max(0, video.currentTime + Number(time)); } else { const duration = video.duration; video.currentTime = (time * video.duration) / 10; } } function isInViewport(element) { const rect = element.getBoundingClientRect(); return (rect.y > 0) && (rect.y < (window.innerHeight / 2)); // return ((rect.height + rect.y) > 0); } function syncPlayerSettings(exportMode = false) { videoPlayerRefresher(); const playerQuality = getQuality(); const playerAudible = !isMuted(); if (exportMode) { localStorage.setItem("quality", playerQuality); localStorage.setItem("audible", playerAudible); } const syncedQuality = localStorage.getItem("quality") || playerQuality; const syncedAudible = (localStorage.getItem("audible") || String(playerAudible)) === "true"; if (syncedQuality !== playerQuality) { toggleQuality(); } if (syncedAudible !== playerAudible) { toggleSound(); } } document.addEventListener("keydown", e => { console.log(e.target); if (e.target.id === SELECTORS.SEARCH_BOX_ID) { // don't use media controls if user is currently typing in search bar return; } videoPlayerRefresher(); console.log(e.code); switch(e.code) { case "KeyF": toggleFullscreen(); break; case "KeyM": toggleSound(); break; case "KeyQ": toggleQuality(); break; case "Space": e.preventDefault(); e.stopImmediatePropagation(); togglePlayState(); break; case "KeyA": toggleFullscreen(); toggleSound(true); toggleQuality(true); break; case "ArrowLeft": seekVideo(-5); break; case "ArrowRight": seekVideo(5); break; case "ArrowUp": case "ArrowDown": // this is only to avoid clashes with Redgifs fullscreen behavoiur because their code is poorly written if (document.fullscreen) { e.preventDefault(); e.stopImmediatePropagation(); } break; case "Digit0": case "Digit1": case "Digit2": case "Digit3": case "Digit4": case "Digit5": case "Digit6": case "Digit7": case "Digit8": case "Digit9": seekVideo(Number(e.code[5]), true); break; default: console.log("Register key press", e.code); } }); // change player based on scroll position let lastKnownScrollPosition = 0; let ticking = false; document.addEventListener('scroll', function(e) { lastKnownScrollPosition = window.scrollY; if (!ticking) { window.requestAnimationFrame(function() { const newVideoElement = getPlayerInSight(); if (videoElement !== newVideoElement) { console.log("Current video player changed to play", newVideoElement); } videoElement = newVideoElement; ticking = false; }); ticking = true; } }); window.addEventListener("blur", function(event) { syncPlayerSettings(true); }, false); window.addEventListener("focus", function(event) { window.setTimeout(syncPlayerSettings, 100); }, false); window.addEventListener("load", (event) => { syncPlayerSettings(); }); })();