您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display live chat while watching YouTube videos in fullscreen mode
// ==UserScript== // @name YouTube Live Chat in Fullscreen // @namespace https://gf.zukizuki.org/en/users/781396 // @version 1.8 // @description Display live chat while watching YouTube videos in fullscreen mode // @author YAD // @license MIT // @icon https://www.iconpacks.net/icons/1/free-icon-video-837.png // @match *://*.youtube.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // Load settings from localStorage or set defaults let chatboxWidth = localStorage.getItem('chatboxWidth') || 350; let chatboxHeight = localStorage.getItem('chatboxHeight') || 600; let chatboxOpacity = localStorage.getItem('chatboxOpacity') || 0.65; let chatboxPosX = localStorage.getItem('chatboxPosX') || 420; let chatboxPosY = localStorage.getItem('chatboxPosY') || -320; let backgroundColor = localStorage.getItem('backgroundColor') || '#000000'; let backgroundOpacity = localStorage.getItem('backgroundOpacity') || 0.5; // CSS styles for transparency function getStyles() { return ` yt-live-chat-header-renderer, yt-live-chat-message-input-renderer, #container.yt-live-chat-restricted-participation-renderer, yt-live-chat-renderer { background: rgba(${hexToRgb(backgroundColor)}, ${backgroundOpacity}) !important; // Adjust background color overflow: hidden; } .draggable { cursor: move; } `; } // Convert hex color to RGB function hexToRgb(hex) { const bigint = parseInt(hex.slice(1), 16); const r = (bigint >> 16) & 255; const g = (bigint >> 8) & 255; const b = bigint & 255; return `${r}, ${g}, ${b}`; } // Function to apply styles to the iframe document function applyStylesToIframe(iframeDoc) { const styleTag = iframeDoc.createElement('style'); styleTag.textContent = getStyles(); iframeDoc.head.appendChild(styleTag); } // Function to apply styles to the chatbox on load and fullscreen change function applyStyles() { const iframe = document.querySelector('iframe#chatframe'); if (iframe) { setTimeout(() => { applyStylesToIframe(iframe.contentDocument || iframe.contentWindow.document); }, 2000); // Adding a 2secs delay to ensure the iframe loads } } // Create settings modal const settingsModal = document.createElement('div'); settingsModal.style.position = 'fixed'; settingsModal.style.top = '50%'; settingsModal.style.left = '50%'; settingsModal.style.transform = 'translate(-50%, -50%)'; settingsModal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; settingsModal.style.color = 'white'; settingsModal.style.padding = '20px'; settingsModal.style.borderRadius = '10px'; settingsModal.style.zIndex = '10001'; settingsModal.style.display = 'none'; // Create the title const title = document.createElement('h3'); title.innerText = 'Chatbox Settings'; settingsModal.appendChild(title); // Create width input const widthLabel = document.createElement('label'); widthLabel.innerText = 'Width: '; const widthInput = document.createElement('input'); widthInput.type = 'number'; widthInput.id = 'chatWidth'; widthInput.value = chatboxWidth; widthInput.style.width = '80px'; widthLabel.appendChild(widthInput); widthLabel.appendChild(document.createTextNode(' px')); settingsModal.appendChild(widthLabel); settingsModal.appendChild(document.createElement('br')); // Create height input const heightLabel = document.createElement('label'); heightLabel.innerText = 'Height: '; const heightInput = document.createElement('input'); heightInput.type = 'number'; heightInput.id = 'chatHeight'; heightInput.value = chatboxHeight; heightInput.style.width = '80px'; heightLabel.appendChild(heightInput); heightLabel.appendChild(document.createTextNode(' px')); settingsModal.appendChild(heightLabel); settingsModal.appendChild(document.createElement('br')); // Create opacity slider const opacityLabel = document.createElement('label'); opacityLabel.innerText = 'Chat Opacity: '; const opacitySlider = document.createElement('input'); opacitySlider.type = 'range'; opacitySlider.id = 'chatOpacity'; opacitySlider.min = '0'; opacitySlider.max = '1'; opacitySlider.step = '0.1'; opacitySlider.value = chatboxOpacity; opacityLabel.appendChild(opacitySlider); settingsModal.appendChild(opacityLabel); settingsModal.appendChild(document.createElement('br')); // Create background color input const bgColorLabel = document.createElement('label'); bgColorLabel.innerText = 'Background Color: '; const bgColorInput = document.createElement('input'); bgColorInput.type = 'color'; bgColorInput.value = backgroundColor; bgColorLabel.appendChild(bgColorInput); settingsModal.appendChild(bgColorLabel); settingsModal.appendChild(document.createElement('br')); // Create background opacity slider const bgOpacityLabel = document.createElement('label'); bgOpacityLabel.innerText = 'Background Transparency: '; const bgOpacitySlider = document.createElement('input'); bgOpacitySlider.type = 'range'; bgOpacitySlider.id = 'bgOpacity'; bgOpacitySlider.min = '0'; bgOpacitySlider.max = '1'; bgOpacitySlider.step = '0.1'; bgOpacitySlider.value = backgroundOpacity; bgOpacityLabel.appendChild(bgOpacitySlider); settingsModal.appendChild(bgOpacityLabel); settingsModal.appendChild(document.createElement('br')); // Create X position slider const posXLabel = document.createElement('label'); posXLabel.innerText = 'X Position: '; const posXSlider = document.createElement('input'); posXSlider.type = 'range'; posXSlider.id = 'chatPosX'; posXSlider.min = `-${window.innerWidth}`; posXSlider.max = `${window.innerWidth}`; posXSlider.value = chatboxPosX; posXLabel.appendChild(posXSlider); settingsModal.appendChild(posXLabel); settingsModal.appendChild(document.createElement('br')); // Create Y position slider const posYLabel = document.createElement('label'); posYLabel.innerText = 'Y Position: '; const posYSlider = document.createElement('input'); posYSlider.type = 'range'; posYSlider.id = 'chatPosY'; posYSlider.min = `-${window.innerHeight}`; posYSlider.max = `${window.innerHeight}`; posYSlider.value = chatboxPosY; posYLabel.appendChild(posYSlider); settingsModal.appendChild(posYLabel); settingsModal.appendChild(document.createElement('br')); // Create apply button const applyButton = document.createElement('button'); applyButton.innerText = 'Apply'; applyButton.id = 'applySettings'; settingsModal.appendChild(applyButton); // Create reset button const resetButton = document.createElement('button'); resetButton.innerText = 'Reset'; resetButton.id = 'resetSettings'; settingsModal.appendChild(resetButton); document.body.appendChild(settingsModal); // Handle settings button click (open modal) const settingsButton = document.createElement('button'); settingsButton.innerText = '⚙'; settingsButton.style.position = 'fixed'; settingsButton.style.top = '2%'; settingsButton.style.right = '2%'; settingsButton.style.zIndex = '10000'; settingsButton.style.display = 'none'; settingsButton.addEventListener('click', () => { settingsModal.style.display = 'block'; }); document.body.appendChild(settingsButton); // Update iframe settings in real-time function updateChatbox() { const iframe = document.querySelector('iframe#chatframe'); if (iframe) { iframe.style.width = `${chatboxWidth}px`; iframe.style.height = `${chatboxHeight}px`; iframe.style.position = 'fixed'; iframe.style.left = `${(window.innerWidth / 2) + parseInt(chatboxPosX)}px`; iframe.style.top = `${(window.innerHeight / 2) + parseInt(chatboxPosY)}px`; iframe.style.opacity = chatboxOpacity; iframe.style.borderRadius = '12px'; applyStyles(); } } // Handle apply button click applyButton.addEventListener('click', () => { // Update settings chatboxWidth = widthInput.value; chatboxHeight = heightInput.value; chatboxOpacity = opacitySlider.value; backgroundColor = bgColorInput.value; backgroundOpacity = bgOpacitySlider.value; chatboxPosX = posXSlider.value; chatboxPosY = posYSlider.value; // Save settings to localStorage localStorage.setItem('chatboxWidth', chatboxWidth); localStorage.setItem('chatboxHeight', chatboxHeight); localStorage.setItem('chatboxOpacity', chatboxOpacity); localStorage.setItem('backgroundColor', backgroundColor); localStorage.setItem('backgroundOpacity', backgroundOpacity); localStorage.setItem('chatboxPosX', chatboxPosX); localStorage.setItem('chatboxPosY', chatboxPosY); settingsModal.style.display = 'none'; updateChatbox(); }); // Handle reset settings resetButton.addEventListener('click', () => { localStorage.removeItem('chatboxWidth'); localStorage.removeItem('chatboxHeight'); localStorage.removeItem('chatboxOpacity'); localStorage.removeItem('backgroundColor'); localStorage.removeItem('backgroundOpacity'); localStorage.removeItem('chatboxPosX'); localStorage.removeItem('chatboxPosY'); // Reset to defaults chatboxWidth = 350; chatboxHeight = 600; chatboxOpacity = 0.65; backgroundColor = '#000000'; backgroundOpacity = 0.5; chatboxPosX = 420; chatboxPosY = -320; // Update UI elements widthInput.value = chatboxWidth; heightInput.value = chatboxHeight; opacitySlider.value = chatboxOpacity; bgColorInput.value = backgroundColor; bgOpacitySlider.value = backgroundOpacity; posXSlider.value = chatboxPosX; posYSlider.value = chatboxPosY; updateChatbox(); // Apply reset settings }); // Handle slider inputs for real-time updates opacitySlider.addEventListener('input', () => { chatboxOpacity = opacitySlider.value; updateChatbox(); }); bgOpacitySlider.addEventListener('input', () => { backgroundOpacity = bgOpacitySlider.value; updateChatbox(); }); bgColorInput.addEventListener('input', () => { backgroundColor = bgColorInput.value; updateChatbox(); }); widthInput.addEventListener('input', () => { chatboxWidth = widthInput.value; updateChatbox(); }); heightInput.addEventListener('input', () => { chatboxHeight = heightInput.value; updateChatbox(); }); posXSlider.addEventListener('input', () => { chatboxPosX = posXSlider.value; updateChatbox(); }); posYSlider.addEventListener('input', () => { chatboxPosY = posYSlider.value; updateChatbox(); }); // Function to adjust slider value with scroll wheel function adjustSliderValue(slider, delta) { const step = parseFloat(slider.step) || 10; const min = parseFloat(slider.min) || 0; const max = parseFloat(slider.max) || 100; let value = parseFloat(slider.value) || 0; value += delta * step; if (value < min) value = min; if (value > max) value = max; slider.value = value; slider.dispatchEvent(new Event('input')); } // Handle mouse scroll on sliders document.querySelectorAll('input[type="range"]').forEach(slider => { slider.addEventListener('wheel', event => { event.preventDefault(); const delta = Math.sign(event.deltaY) * -1; adjustSliderValue(slider, delta); }); // Handle arrow key controls on sliders slider.addEventListener('keydown', event => { if (event.key === 'ArrowUp' && slider.id === 'chatPosY') { adjustSliderValue(slider, -1); } else if (event.key === 'ArrowDown' && slider.id === 'chatPosY') { adjustSliderValue(slider, 1); } else if (event.key === 'ArrowLeft' && slider.id === 'chatPosX') { adjustSliderValue(slider, -1); } else if (event.key === 'ArrowRight' && slider.id === 'chatPosX') { adjustSliderValue(slider, 1); } else if ((event.key === 'ArrowUp' || event.key === 'ArrowRight') && slider.id !== 'chatPosX' && slider.id !== 'chatPosY') { adjustSliderValue(slider, 1); } else if ((event.key === 'ArrowDown' || event.key === 'ArrowLeft') && slider.id !== 'chatPosX' && slider.id !== 'chatPosY') { adjustSliderValue(slider, -1); } }); }); // Handle fullscreen changes function handleFullscreenChange() { const iframe = document.querySelector('iframe#chatframe'); if (!iframe) return; const isFullscreen = document.fullscreenElement; if (isFullscreen) { updateChatbox(); applyStyles(); settingsButton.style.display = 'block'; } else { settingsButton.style.display = 'none'; settingsModal.style.display = 'none'; // Reset to default values (do not remove saved settings) iframe.style.width = ''; iframe.style.height = ''; iframe.style.position = ''; iframe.style.left = ''; iframe.style.top = ''; iframe.style.opacity = ''; } } // Listen for fullscreen changes document.addEventListener('fullscreenchange', handleFullscreenChange); // Initial chatbox update updateChatbox(); applyStylesOnLoad(); })();