您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Block autoplay before user interaction on most websites
当前为
// ==UserScript== // @name Disable autoplay // @namespace https://www.androidacy.com/ // @version 2.5.6 // @description Block autoplay before user interaction on most websites // @author Androidacy // @include * // @icon https://www.androidacy.com/wp-content/uploads/cropped-cropped-cropped-cropped-New-Project-32-69C2A87-1-192x192.jpg // @grant none // @run-at document-start // ==/UserScript== (() => { const mediaTags = ['video', 'audio'] const processedAttr = 'data-disable-autoplay-processed' const allowedValue = `__pb_allowed_${Math.random().toString(36).substr(2, 10)}` const proximityThreshold = 100 // pixels const debugLog = (...args) => { console.debug('[DisableAutoplay]', ...args) } const warnLog = (...args) => { console.warn('[DisableAutoplay]', ...args) } const generateRandomString = (length = 6) => { const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' let result = '' for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)) } return result } const disableAutoplay = (media) => { if (media.hasAttribute(processedAttr)) { debugLog('Already processed media element:', media) return } media.setAttribute(processedAttr, 'true') debugLog('Processing media element:', media) if (media.hasAttribute('autoplay')) { media.removeAttribute('autoplay') debugLog('Removed autoplay attribute from media:', media) } if (!media.paused) { media.pause() debugLog('Paused media element:', media) } const originalPlay = media.play media.play = function (...args) { const allowed = media.getAttribute('data-pb-allowed') if (allowed === allowedValue) { debugLog('Playing media element:', media) return originalPlay.apply(this, args) } warnLog('Autoplay blocked for media element:', media) return Promise.reject(new Error('Autoplay is disabled by a userscript.')) } const handler = (event) => { if (!event.isTrusted) { warnLog('Ignored untrusted event:', event) return } media.setAttribute('data-pb-allowed', allowedValue) debugLog('User interaction detected:', event.type, 'on', event.target) media.play().catch(err => warnLog('Error playing media after user interaction:', err, media)) media.removeEventListener('click', handler) media.removeEventListener('touchstart', handler) removeCoverListeners(media, handler) } const addListeners = () => { media.addEventListener('click', handler, { once: true, passive: false }) media.addEventListener('touchstart', handler, { once: true, passive: false }) debugLog('Added click and touchstart event listeners to media element:', media) } addListeners() addCoverListeners(media, handler) } const addCoverListeners = (media, handler) => { const covers = findCoverElements(media) covers.forEach(cover => { cover.addEventListener('click', handler, { once: true, passive: false }) cover.addEventListener('touchstart', handler, { once: true, passive: false }) debugLog('Added event listeners to cover element:', cover) }) } const removeCoverListeners = (media, handler) => { const covers = findCoverElements(media) covers.forEach(cover => { cover.removeEventListener('click', handler) cover.removeEventListener('touchstart', handler) debugLog('Removed event listeners from cover element:', cover) }) } const findCoverElements = (media) => { const covers = [] const mediaRect = media.getBoundingClientRect() const parent = media.parentElement if (!parent) return covers Array.from(parent.children).forEach(sibling => { if (sibling === media) return const style = window.getComputedStyle(sibling) const { position, display, visibility, pointerEvents } = style if (display === 'none' || visibility === 'hidden' || pointerEvents === 'none') return if (!['absolute', 'fixed', 'relative'].includes(position)) return const siblingRect = sibling.getBoundingClientRect() if (isOverlapping(mediaRect, siblingRect) || isWithinProximity(mediaRect, siblingRect)) { covers.push(sibling) } }) return covers } const isOverlapping = (rect1, rect2) => { const threshold = 0.3 const intersection = { left: Math.max(rect1.left, rect2.left), right: Math.min(rect1.right, rect2.right), top: Math.max(rect1.top, rect2.top), bottom: Math.min(rect1.bottom, rect2.bottom) } const width = intersection.right - intersection.left const height = intersection.bottom - intersection.top if (width <= 0 || height <= 0) return false const areaIntersection = width * height const areaMedia = rect1.width * rect1.height return (areaIntersection / areaMedia) >= threshold } const isWithinProximity = (rect1, rect2) => { const proximity = proximityThreshold const horizontallyClose = Math.abs(rect1.left - rect2.left) <= proximity || Math.abs(rect1.right - rect2.right) <= proximity || Math.abs(rect1.left - rect2.right) <= proximity || Math.abs(rect1.right - rect2.left) <= proximity const verticallyClose = Math.abs(rect1.top - rect2.top) <= proximity || Math.abs(rect1.bottom - rect2.bottom) <= proximity || Math.abs(rect1.top - rect2.bottom) <= proximity || Math.abs(rect1.bottom - rect2.top) <= proximity return horizontallyClose || verticallyClose } const processMediaElements = () => { mediaTags.forEach(tag => { document.querySelectorAll(tag).forEach(media => { disableAutoplay(media) }) }) } const observeMedia = () => { const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType !== Node.ELEMENT_NODE) return mediaTags.forEach(tag => { if (node.matches(tag)) { debugLog('New media element added:', node) disableAutoplay(node) } node.querySelectorAll(tag).forEach(media => { debugLog('New nested media element added:', media) disableAutoplay(media) }) }) }) }) }) try { observer.observe(document.body, { childList: true, subtree: true }) debugLog('Started observing DOM for new media elements') } catch (error) { warnLog('Failed to observe DOM:', error) } } const init = () => { debugLog('Initializing Disable autoplay userscript') processMediaElements() } init() if (document.readyState === 'complete' || document.readyState === 'interactive') { observeMedia() } else { document.addEventListener('DOMContentLoaded', observeMedia, { once: true }) } })()