ScrollBuddy

简约的滚动按钮

  1. // ==UserScript==
  2. // @name ScrollBuddy
  3. // @namespace https://gf.qytechs.cn/en/users/1451802
  4. // @version 1.0
  5. // @license MIT
  6. // @description Minimalist button for scrolling
  7. // @description:de Minimalistische Schaltfläche zum Scrollen
  8. // @description:es Botón minimalista para desplazarse
  9. // @description:fr Bouton minimaliste pour scroller
  10. // @description:it Pulsante minimalista per lo scorrimento
  11. // @description:ru Минималистичная кнопка для прокрутки
  12. // @description:zh-CN 简约的滚动按钮
  13. // @description:zh-TW 簡約的捲動按鈕
  14. // @description:ja ミニマリストスクロールボタン
  15. // @description:ko 미니멀리스트 스크롤 버튼
  16. // @author NormalRandomPeople (https://github.com/NormalRandomPeople)
  17. // @icon https://www.svgrepo.com/show/533633/arrows-up-down.svg
  18. // @match *://*/*
  19. // @grant GM_addStyle
  20. // @run-at document-end
  21. // @compatible chrome
  22. // @compatible firefox
  23. // @compatible opera
  24. // @compatible brave
  25. // ==/UserScript==
  26.  
  27. (function() {
  28. 'use strict';
  29.  
  30. if (window !== window.top) {
  31. return;
  32. }
  33.  
  34. if (document.querySelector('.scroll-toggle-button')) {
  35. return;
  36. }
  37.  
  38. let smoothScrolling = localStorage.getItem('smoothScrolling') !== null ? JSON.parse(localStorage.getItem('smoothScrolling')) : true;
  39. let fixToBottom = localStorage.getItem('fixToBottom') !== null ? JSON.parse(localStorage.getItem('fixToBottom')) : false;
  40. let fixToTop = localStorage.getItem('fixToTop') !== null ? JSON.parse(localStorage.getItem('fixToTop')) : false;
  41.  
  42. const button = document.createElement('button');
  43. button.className = 'scroll-toggle-button';
  44. button.textContent = '↓';
  45. button.style.position = 'fixed';
  46. button.style.bottom = '20px';
  47. button.style.right = '20px';
  48. button.style.zIndex = '9999999999';
  49. button.style.padding = '12px';
  50. button.style.borderRadius = '50%';
  51. button.style.backgroundColor = '#333';
  52. button.style.color = 'white';
  53. button.style.border = 'none';
  54. button.style.fontSize = '30px';
  55. button.style.cursor = 'pointer';
  56. button.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';
  57. button.style.outline = 'none';
  58.  
  59. function updateButton() {
  60. if (fixToTop) {
  61. button.textContent = '↑';
  62. button.onclick = () => scrollToTop();
  63. } else if (fixToBottom) {
  64. button.textContent = '↓';
  65. button.onclick = () => scrollToBottom();
  66. } else {
  67. const isAtBottom = (window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight;
  68. const isAtTop = window.scrollY === 0;
  69.  
  70. if (isAtTop) {
  71. button.textContent = '↓';
  72. button.onclick = () => scrollToBottom();
  73. } else if (isAtBottom) {
  74. button.textContent = '↑';
  75. button.onclick = () => scrollToTop();
  76. }
  77. }
  78. }
  79.  
  80. function scrollToBottom() {
  81. window.scrollTo({ top: document.documentElement.scrollHeight - window.innerHeight, behavior: smoothScrolling ? 'smooth' : 'auto' });
  82. }
  83.  
  84. function scrollToTop() {
  85. window.scrollTo({ top: 0, behavior: smoothScrolling ? 'smooth' : 'auto' });
  86. }
  87.  
  88. updateButton();
  89. window.addEventListener('scroll', updateButton);
  90. document.body.appendChild(button);
  91.  
  92. GM_addStyle(`
  93. .scroll-toggle-button:hover {
  94. background-color: #555;
  95. transform: scale(1.1);
  96. }
  97.  
  98. .scroll-toggle-button:active {
  99. transform: scale(0.95);
  100. }
  101.  
  102. .custom-context-menu div {
  103. padding: 8px 15px;
  104. cursor: pointer;
  105. transition: background-color 0.2s ease;
  106. text-align: left;
  107. }
  108.  
  109. .custom-context-menu div:hover {
  110. background-color: #444;
  111. }
  112.  
  113. .custom-context-menu div:active {
  114. background-color: #555;
  115. }
  116.  
  117. .custom-context-menu div.selected {
  118. background-color: #333;
  119. }
  120. `);
  121.  
  122. function createContextMenu(event) {
  123. event.preventDefault();
  124.  
  125. const existingMenu = document.querySelector('.custom-context-menu');
  126. if (existingMenu) {
  127. existingMenu.remove();
  128. }
  129.  
  130. const menu = document.createElement('div');
  131. menu.className = 'custom-context-menu';
  132. menu.style.position = 'absolute';
  133. menu.style.backgroundColor = '#333';
  134. menu.style.color = 'white';
  135. menu.style.borderRadius = '5px';
  136. menu.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';
  137. menu.style.padding = '10px';
  138. menu.style.fontFamily = 'Arial, sans-serif';
  139. menu.style.fontSize = '14px';
  140. menu.style.zIndex = '99999999999';
  141. const buttonRect = button.getBoundingClientRect();
  142. let menuLeft = buttonRect.left + window.scrollX - 220;
  143. let menuTop = buttonRect.top + window.scrollY - 130;
  144. const screenWidth = window.innerWidth;
  145. const menuWidth = 150;
  146. const marginRight = 30;
  147. if (menuLeft + menuWidth > screenWidth - marginRight) {
  148. menuLeft = screenWidth - menuWidth - marginRight;
  149. }
  150.  
  151. const screenHeight = window.innerHeight;
  152. if (menuTop < 0) {
  153. menuTop = buttonRect.bottom + window.scrollY + 20;
  154. }
  155.  
  156. menu.style.left = `${menuLeft}px`;
  157. menu.style.top = `${menuTop}px`;
  158.  
  159. const smoothScrollingOption = document.createElement('div');
  160. smoothScrollingOption.textContent = smoothScrolling ? '✓ Enable Smooth Scrolling' : 'Enable Smooth Scrolling';
  161. smoothScrollingOption.onclick = () => {
  162. smoothScrolling = !smoothScrolling;
  163. localStorage.setItem('smoothScrolling', smoothScrolling);
  164. updateButton();
  165. menu.remove();
  166. };
  167.  
  168. const fixToBottomOption = document.createElement('div');
  169. fixToBottomOption.textContent = fixToBottom ? '✓ Fix to Bottom' : 'Fix to Bottom';
  170. fixToBottomOption.onclick = () => {
  171. fixToBottom = !fixToBottom;
  172. if (fixToBottom) {
  173. fixToTop = false;
  174. }
  175. localStorage.setItem('fixToBottom', fixToBottom);
  176. localStorage.setItem('fixToTop', fixToTop);
  177. updateButton();
  178. menu.remove();
  179. };
  180.  
  181. const fixToTopOption = document.createElement('div');
  182. fixToTopOption.textContent = fixToTop ? '✓ Fix to Top' : 'Fix to Top';
  183. fixToTopOption.onclick = () => {
  184. fixToTop = !fixToTop;
  185. if (fixToTop) {
  186. fixToBottom = false;
  187. }
  188. localStorage.setItem('fixToTop', fixToTop);
  189. localStorage.setItem('fixToBottom', fixToBottom);
  190. updateButton();
  191. menu.remove();
  192. };
  193.  
  194. menu.appendChild(smoothScrollingOption);
  195. menu.appendChild(fixToBottomOption);
  196. menu.appendChild(fixToTopOption);
  197. document.body.appendChild(menu);
  198. document.addEventListener('click', () => menu.remove(), { once: true });
  199. }
  200.  
  201. button.addEventListener('contextmenu', createContextMenu);
  202. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址