您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add up/down navigation buttons to scroll to top or bottom of the page, hide during fullscreen, plus small toggle to make buttons transparent
当前为
// ==UserScript== // @name scroll up and down buttons // @namespace http://tampermonkey.net/ // @version 1.3 // @description Add up/down navigation buttons to scroll to top or bottom of the page, hide during fullscreen, plus small toggle to make buttons transparent // @author You // @match *://*/* // @grant none // @license Apache 2.0 // ==/UserScript== (function () { 'use strict'; if (window.top !== window.self) return; if (document.body && document.body.children.length === 1) { const onlyChild = document.body.children[0]; const tag = onlyChild.tagName.toLowerCase(); if (['img', 'video', 'audio', 'embed', 'object'].includes(tag)) return; } let scrollAnimationId = null; function smoothScrollTo(targetY) { if (scrollAnimationId) cancelAnimationFrame(scrollAnimationId); const startY = window.scrollY; const distance = targetY - startY; const duration = 1000; const startTime = performance.now(); function step(currentTime) { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const ease = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress; window.scrollTo(0, startY + distance * ease); if (progress < 1) { scrollAnimationId = requestAnimationFrame(step); } else { scrollAnimationId = null; } } scrollAnimationId = requestAnimationFrame(step); } function stopScroll() { if (scrollAnimationId) { cancelAnimationFrame(scrollAnimationId); scrollAnimationId = null; } } ['mousedown', 'wheel', 'touchstart', 'keydown'].forEach(evt => { window.addEventListener(evt, stopScroll, { passive: true }); }); // --- Styles (use classes so toggling is easy) --- const style = document.createElement('style'); style.textContent = ` .tm-scroll-container { position: fixed; bottom: 10px; right: 10px; display: flex; flex-direction: column; gap: 6px; z-index: 9999999; pointer-events: auto; align-items: center; } .tm-scroll-btn { background-color: #333; color: white; font-size: 17px; padding: 8px 12px; border: none; border-radius: 6px; cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,0.3); transition: background-color 0.2s, opacity 0.2s; } .tm-toggle-btn { width: 28px; height: 28px; padding: 0; border-radius: 50%; font-size: 14px; display:flex; align-items:center; justify-content:center; background-color: #555; color: #fff; border:none; cursor:pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.3); } .tm-scroll-btn.transparent { opacity: 0; } .tm-scroll-btn.transparent { opacity: 0.1; } .tm-toggle-btn.active { background-color: #1a73e8; color: #fff; } `; document.head.appendChild(style); // Container const container = document.createElement('div'); container.className = 'tm-scroll-container'; // Toggle button (small, visible) const toggleBtn = document.createElement('button'); toggleBtn.className = 'tm-toggle-btn'; toggleBtn.title = 'Toggle button transparency'; toggleBtn.setAttribute('aria-pressed', 'false'); toggleBtn.textContent = '◐'; // icon-like visual container.appendChild(toggleBtn); // Up button const upBtn = document.createElement('button'); upBtn.className = 'tm-scroll-btn'; upBtn.textContent = '▲'; upBtn.title = 'Scroll to top'; upBtn.onclick = () => smoothScrollTo(0); // Down button const downBtn = document.createElement('button'); downBtn.className = 'tm-scroll-btn'; downBtn.textContent = '▼'; downBtn.title = 'Scroll to bottom'; downBtn.onclick = () => smoothScrollTo(document.documentElement.scrollHeight || document.body.scrollHeight); container.appendChild(upBtn); container.appendChild(downBtn); document.body.appendChild(container); // Persisted state key const STORAGE_KEY = 'tm_scroll_transparent_v1'; // Apply saved state (if any) function applyTransparencyState(state) { if (state) { upBtn.classList.add('transparent'); downBtn.classList.add('transparent'); toggleBtn.classList.add('active'); toggleBtn.setAttribute('aria-pressed', 'true'); toggleBtn.textContent = '◑'; } else { upBtn.classList.remove('transparent'); downBtn.classList.remove('transparent'); toggleBtn.classList.remove('active'); toggleBtn.setAttribute('aria-pressed', 'false'); toggleBtn.textContent = '◐'; } try { localStorage.setItem(STORAGE_KEY, state ? '1' : '0'); } catch (e) { /* ignore storage errors */ } } // Initialize from storage let saved = null; try { saved = localStorage.getItem(STORAGE_KEY); } catch (e) { saved = null; } applyTransparencyState(saved === '1'); // Toggle handler toggleBtn.addEventListener('click', (e) => { const enabled = upBtn.classList.contains('transparent'); applyTransparencyState(!enabled); // keep the small toggle visible (we only change the two main buttons) e.stopPropagation(); }); // Hide during fullscreen document.addEventListener('fullscreenchange', () => { container.style.display = document.fullscreenElement ? 'none' : 'flex'; }); // Ensure container is removed/hidden on pages that replace body later (basic guard) const observer = new MutationObserver(() => { if (!document.body || document.body.contains(container) === false) { if (document.body) document.body.appendChild(container); } }); observer.observe(document.documentElement || document, { childList: true, subtree: true }); })();