Smooth Scrolling

Scrolls the page x times per second when the button is held

当前为 2021-03-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Smooth Scrolling
  3. // @description Scrolls the page x times per second when the button is held
  4. // @version 1.0.0
  5. // @namespace https://gf.qytechs.cn/en/users/55535-sllypper
  6. // @author sllypper
  7. // @match *://forums.spacebattles.com/*
  8. // @match *://forums.sufficientvelocity.com/*
  9. // @match *://forum.questionablequesting.com/*
  10. // @match *://fanfiction.net/*
  11. // @match *://archiveofourown.org/*
  12. // @match *://turb0translation.blogspot.com/*
  13. // @grant none
  14. // @todo make keybinds easily configurable
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. // Smooth Scrolling Settings
  21.  
  22. // how much it scrolls every time (in pixels)
  23. let scrollAmount = 16;
  24.  
  25. // how long between ticks (in ms)
  26. // 16.66667 = 60 frames per second
  27. // not used if experimental is true
  28. let scrollPeriod = 16.66667;
  29.  
  30. // how much holding Shift will multiply the scrollAmount
  31. let shiftSpeedMod = 2.0;
  32.  
  33. //
  34.  
  35. // Experimental settings
  36.  
  37. // Use the alternative experimental Scroller
  38. // it's bound to your screen framerate
  39. // is supposed to be smoother
  40. let experimental = true;
  41.  
  42. // Scroll Speed in times per second
  43. // set to 0 to match your refresh rate (smooth perfection)
  44. // values above your framerate scrolls every frame
  45. let fps = 0
  46.  
  47. // programming magic stuff
  48.  
  49. const states = {
  50. NONE: 0,
  51. UP: 1,
  52. SHIFTUP: 2,
  53. DOWN: 3,
  54. SHIFTDOWN: 4
  55. }
  56. let scrollState = states.NONE;
  57. let currScrollAction = null;
  58. let isTyping = false;
  59.  
  60. document.addEventListener('focus', function(evt) {
  61. var target = evt.target;
  62. if((target.nodeName === 'INPUT' && target.type === 'text') || target.nodeName === 'TEXTAREA') isTyping = true;
  63. // else isTyping = false;
  64. }, true);
  65.  
  66. document.addEventListener('blur', function(evt) {
  67. var target = evt.target;
  68. if((target.nodeName === 'INPUT' && target.type === 'text') || target.nodeName === 'TEXTAREA') isTyping = false;
  69. }, true);
  70.  
  71. document.addEventListener("keydown", event => {
  72. // ignore keybindings when text input is focused
  73. if(isTyping || event.isComposing) {
  74. event.stopPropagation();
  75. return;
  76. }
  77. if (event.code === "KeyW" || event.code === "KeyK" || event.code === "ArrowUp") {
  78. if (scrollState !== states.UP && !event.shiftKey) {
  79. clearScrollAction();
  80. scrollState = states.UP;
  81. scrollAction(-scrollAmount);
  82. } else if (scrollState !== states.SHIFTUP && event.shiftKey) {
  83. clearScrollAction();
  84. scrollState = states.SHIFTUP;
  85. scrollAction(-scrollAmount*shiftSpeedMod);
  86. }
  87. } else if (event.code === "KeyS" || event.code === "KeyJ" || event.code === "ArrowDown") {
  88. if (scrollState !== states.DOWN && !event.shiftKey) {
  89. clearScrollAction();
  90. scrollState = states.DOWN;
  91. scrollAction(scrollAmount);
  92. } else if (scrollState !== states.SHIFTDOWN && event.shiftKey) {
  93. clearScrollAction();
  94. scrollState = states.SHIFTDOWN;
  95. scrollAction(scrollAmount*shiftSpeedMod);
  96. }
  97. }
  98. });
  99.  
  100. document.addEventListener("keyup", event => {
  101. switch(event.code) {
  102. case 'KeyW':
  103. case 'KeyK':
  104. case 'KeyJ':
  105. case 'KeyS':
  106. case 'ArrowDown':
  107. case 'ArrowUp':
  108. clearScrollAction();
  109. break
  110. default:
  111. if (event.key === "Shift") {
  112. clearScrollAction();
  113. }
  114. break;
  115. }
  116. });
  117.  
  118. function scrollAction(amount) {
  119. if (experimental) {
  120. scroller.move(amount)
  121. return;
  122. }
  123.  
  124. currScrollAction = setInterval(() => {
  125. window.scrollBy(0, amount);
  126. }, scrollPeriod)
  127. }
  128.  
  129. function clearScrollAction() {
  130. clearInterval(currScrollAction);
  131. currScrollAction = null;
  132. scrollState = states.NONE;
  133. scroller.stop();
  134. }
  135.  
  136. // experimental bit
  137.  
  138. let scroller = new Scroller(fps)
  139.  
  140. function Scroller(fps) {
  141.  
  142. var delay,
  143. time,
  144. frame,
  145. tref,
  146. amount;
  147.  
  148. function loop(timestamp) {
  149. if (fps !== 0) {
  150. // Scroll with fps behavior
  151. if (time === null) {time = timestamp; timestamp = 0}
  152. var seg = Math.floor((timestamp - time) / delay);
  153. if (seg > frame) {
  154. frame = seg;
  155. window.scrollBy(0, amount);
  156. }
  157. } else {
  158. // Scroll every frame behavior
  159. window.scrollBy(0, amount);
  160. }
  161. tref = requestAnimationFrame(loop)
  162. }
  163.  
  164. this.move = function(pixels) {
  165. amount = pixels;
  166. delay = 1000 / fps;
  167. frame = -1;
  168. time = null;
  169. tref = requestAnimationFrame(loop);
  170. }
  171.  
  172. this.stop = function() {
  173. cancelAnimationFrame(tref);
  174. };
  175. }
  176.  
  177. })();

QingJ © 2025

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