// ==UserScript== // @name 双击全屏(使用手机浏览器) // @namespace http://tampermonkey.net/ // @version 1.4 // @description 安卓手机浏览器双击切换全屏,避免输入区域触发,不影响视频操作,键盘弹出时对话框自动抬高 // @author 青野 // @match *://*/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; let lastTapTime = 0; const doubleTapDelay = 300; // 双击间隔时间(毫秒) // 检查是否为可输入元素 function isInputElement(element) { const tagName = element.tagName.toLowerCase(); const inputTags = ['input', 'textarea', 'select']; const isContentEditable = element.isContentEditable; const isInputRole = element.getAttribute('role') === 'textbox'; return inputTags.includes(tagName) || isContentEditable || isInputRole; } // 检查是否在视频控件区域 function isVideoControls(element) { let current = element; while (current) { if (current.tagName && current.tagName.toLowerCase() === 'video') { return false; // 视频元素本身可以双击 } // 检查是否是视频控件容器 const className = current.className || ''; if (typeof className === 'string' && (className.includes('controls') || className.includes('player-controls') || className.includes('video-controls'))) { return true; } current = current.parentElement; } return false; } // 切换全屏 function toggleFullscreen() { if (!document.fullscreenElement && !document.webkitFullscreenElement && !document.mozFullScreenElement && !document.msFullscreenElement) { // 进入全屏 const elem = document.documentElement; if (elem.requestFullscreen) { elem.requestFullscreen(); } else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(); } else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); } else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); } } else { // 退出全屏 if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } } // 双击事件处理 function handleTap(e) { const target = e.target; // 忽略输入元素 if (isInputElement(target)) { return; } // 忽略视频控件区域 if (isVideoControls(target)) { return; } const currentTime = new Date().getTime(); const tapLength = currentTime - lastTapTime; if (tapLength < doubleTapDelay && tapLength > 0) { // 双击检测成功 e.preventDefault(); toggleFullscreen(); lastTapTime = 0; // 重置 } else { lastTapTime = currentTime; } } // 监听触摸结束事件(移动端) document.addEventListener('touchend', function(e) { // 确保只是单点触摸 if (e.changedTouches.length === 1) { handleTap(e); } }, { passive: false }); // 键盘弹出时对话框抬高处理 function handleKeyboardResize() { // 检测可能的对话框元素 const dialogSelectors = [ 'dialog', '[role="dialog"]', '[role="alertdialog"]', '.modal', '.dialog', '.popup', '[class*="modal"]', '[class*="dialog"]', '[class*="popup"]' ]; const visualViewport = window.visualViewport; if (visualViewport) { visualViewport.addEventListener('resize', function() { const keyboardHeight = window.innerHeight - visualViewport.height; dialogSelectors.forEach(selector => { const dialogs = document.querySelectorAll(selector); dialogs.forEach(dialog => { if (dialog.offsetParent !== null) { // 可见的对话框 if (keyboardHeight > 100) { // 键盘可能已弹出 dialog.style.transition = 'transform 0.3s ease'; dialog.style.transform = `translateY(-${keyboardHeight}px)`; } else { dialog.style.transform = 'translateY(0)'; } } }); }); }); visualViewport.addEventListener('scroll', function() { // 保持对话框位置 const scrollTop = visualViewport.offsetTop; dialogSelectors.forEach(selector => { const dialogs = document.querySelectorAll(selector); dialogs.forEach(dialog => { if (dialog.offsetParent !== null && dialog.style.position === 'fixed') { dialog.style.top = `${scrollTop}px`; } }); }); }); } // 备用方案:监听焦点事件 document.addEventListener('focusin', function(e) { if (isInputElement(e.target)) { setTimeout(() => { dialogSelectors.forEach(selector => { const dialogs = document.querySelectorAll(selector); dialogs.forEach(dialog => { if (dialog.offsetParent !== null) { dialog.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }); }); }, 300); } }); document.addEventListener('focusout', function(e) { if (isInputElement(e.target)) { setTimeout(() => { dialogSelectors.forEach(selector => { const dialogs = document.querySelectorAll(selector); dialogs.forEach(dialog => { dialog.style.transform = 'translateY(0)'; }); }); }, 100); } }); } // 初始化键盘处理 handleKeyboardResize(); console.log('🐵 双击全屏脚本已加载 - 作者:青野'); })();