This userscript is designed for mobile browsers, and scrolls page on double tap. Top half of the screen scrolls up, and bottom half scrolls down. Single taps are ignored for a specified timeout while script waits for a second tap, and then get dispatched programmatically.
当前为
// ==UserScript==
// @name Scroll page on double tap (mobile)
// @description This userscript is designed for mobile browsers, and scrolls page on double tap. Top half of the screen scrolls up, and bottom half scrolls down. Single taps are ignored for a specified timeout while script waits for a second tap, and then get dispatched programmatically.
// @version 1.0.0
// @author emvaized
// @license MIT
// @namespace scroll_page_on_double_tap
// @match <all_urls>
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
const amountToScroll = 0.8; // Ratio to screen height, e.g. '0.8' means 80% of screen height
const doubleTapTimeout = 200; // Timeout for second tap in milliseconds
const maxTapMovement = 10; // Maximum movement (in pixels) to qualify as a tap
let lastTapTime = 0; // To track timing between taps
let firstTapEvent = null; // To store the first tap event details
let startX = 0; // Start position for touch
let startY = 0;
document.addEventListener('touchstart', function(event) {
// Only handle single-finger touches
if (event.touches.length === 1) {
startX = event.touches[0].clientX;
startY = event.touches[0].clientY;
}
}, true);
document.addEventListener('touchend', function(event) {
// Only proceed if it’s a single-finger touch and movement is minimal
if (event.changedTouches.length > 1) return; // Ignore multi-touch events
const endX = event.changedTouches[0].clientX;
const endY = event.changedTouches[0].clientY;
const deltaX = Math.abs(endX - startX);
const deltaY = Math.abs(endY - startY);
// If movement exceeds maxTapMovement, consider it a scroll/swipe and ignore
if (deltaX > maxTapMovement || deltaY > maxTapMovement) return;
const currentTime = new Date().getTime();
const tapInterval = currentTime - lastTapTime;
// Prevent default action (including link navigation)
event.preventDefault();
event.stopPropagation();
if (tapInterval < doubleTapTimeout && tapInterval > 0) {
// Double-tap detected within timeout
// Execute custom double-tap action: scroll down
window.scrollBy({
top: (event.changedTouches[0].clientY > (window.screen.height / 2) ? 1 : -1) * window.visualViewport.height * amountToScroll,
behavior: "smooth"
})
// Reset stored event and timing
lastTapTime = 0;
firstTapEvent = null;
} else {
// First tap: store the event and set timeout for single-tap action
firstTapEvent = event;
lastTapTime = currentTime;
setTimeout(() => {
// If no second tap, execute single-tap action
if (firstTapEvent) {
// Trigger click only if it's a single tap, re-dispatching it as a new event
const singleClickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
firstTapEvent.target.dispatchEvent(singleClickEvent);
}
firstTapEvent = null;
}, doubleTapTimeout);
}
}, true);
})();