Smoothscroll

Smooth scrolling everywhere using javascript

当前为 2016-11-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Smoothscroll
  3. // @include http*
  4. // @author Creec Winceptor
  5. // @description Smooth scrolling everywhere using javascript
  6. // @namespace https://greasyfork.org/users/3167
  7. // @run-at document-load
  8. // @grant none
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_registerMenuCommand
  12. // @version 2.2
  13. // ==/UserScript==
  14.  
  15. if (window.top != window.self) //don't run on frames or iframes
  16. return;
  17.  
  18. //DEFAULT SETTINGS HERE
  19. //DO NOT CHANGE ANYTHING HERE ANYMORE, USE SCRIPT COMMANDS -> CONFIGURE SMOOTHSCROLL
  20.  
  21.  
  22. //Smoothness factor value (how strong the smoothing effect is)
  23. //values: 1-(infinite)
  24. var smoothness = 50;
  25.  
  26. //Scroll sensitivity
  27. //values: anything? (default 1.00)
  28. var sensitivity = 1;
  29.  
  30. //Acceleration sensitivity
  31. //values: anything? (default 1.50)
  32. var acceleration = 1;
  33.  
  34. //Refreshrate setting
  35. //values: 30-144 (default = 60/72/120/144 = same as your monitor hz)
  36. var refreshrate = 60;
  37.  
  38.  
  39. //Alternative scrolling multiplier
  40. //values: true/false (try to set this to true if scrolling is too slow/doesn't work)
  41. var alternative_sensitivity_multiplier = false;
  42.  
  43.  
  44. //CODE STARTS HERE
  45.  
  46. var DEBUG = false;
  47.  
  48. var WEBKIT = false;
  49.  
  50. console.log("Loading smoothscroll...");
  51.  
  52. var baserefreshrate = 60; //DO NOT CHANGE THIS EVER
  53. if (smoothness>100)
  54. {
  55. smoothness = 100;
  56. }
  57.  
  58. if (refreshrate <= 30 || refreshrate>144)
  59. {
  60. refreshrate = 144;
  61. }
  62.  
  63. function InitSmoothscroll()
  64. {
  65. LoadConfig();
  66.  
  67. InitConfigmenu();
  68.  
  69. var startposition = false;
  70. var targetposition = 0;
  71. var position = 0;
  72.  
  73. //var scrollfocus = //ss$('body');
  74. var scrollfocus = document.body;
  75. var mousemoved = true;
  76. function hasScrollBarVisible(element)
  77. {
  78. //return (document.documentElement.scrollHeight !== document.documentElement.clientHeight);
  79. // Get the computed style of the body element
  80. var cStyle = element.currentStyle||window.getComputedStyle(element, "");
  81. // Check the overflow and overflowY properties for "auto" and "visible" values
  82. var scrollbar1 = cStyle.overflow == "scroll" || cStyle.overflowY == "scroll";
  83.  
  84. var scrollbar2 = cStyle.overflow == "auto" || cStyle.overflowY == "auto";
  85. var scrollbar = scrollbar1 || scrollbar2;
  86. return scrollbar;
  87. }
  88.  
  89.  
  90. function hasscrollbars(scrollfocus)
  91. {
  92. var hasvisiblescrollbars = hasScrollBarVisible(scrollfocus);
  93. return hasvisiblescrollbars;
  94. /*
  95. var parentelement = //ss$(scrollfocus).parent();
  96. if ( //ss$(parentelement))
  97. {
  98. if (//ss$(parentelement).is("textarea") || //ss$(scrollfocus).is("textarea") || //ss$(parentelement).is("article") || //ss$(parentelement).is("article"))
  99. {
  100. return true;
  101. }
  102. else
  103. {
  104. if (//ss$(parentelement).hasClass( "yt-scrollbar" ) || //ss$(scrollfocus).hasClass( "yt-scrollbar" ))
  105. {
  106. return true;
  107. }
  108. return hasvisiblescrollbars;
  109. }
  110. }
  111. else
  112. {
  113. return hasvisiblescrollbars;
  114. }
  115. return false;
  116. */
  117. }
  118.  
  119. var scroll_timeout = null;
  120.  
  121. function UpdatePosition(element)
  122. {
  123. //gameLoop();
  124. var interpolation = 3;
  125. var animationduration = Math.round(1000/(refreshrate*interpolation));
  126. var relativeratio = Math.round(( 1/(1+smoothness)/interpolation*refreshrate/baserefreshrate )*1000)/1000;
  127. var positiondelta = scrollpositiondelta(element);
  128. var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio);
  129. var rounddelta = Math.ceil(smoothdelta);
  130. //var smoothdelta = positiondelta*relativeratio;
  131. if (positiondelta<0)
  132. {
  133. smoothdelta = smoothdelta*(-1);
  134. rounddelta = rounddelta*(-1);
  135. }
  136.  
  137. if (Math.abs( rounddelta ) < 1 )
  138. {
  139. if (Math.abs( positiondelta ) > 1 )
  140. {
  141. scroll_timeout = setTimeout(function() {
  142. element.scrollTop = element.scrollTop + rounddelta;
  143. scrollpositiondelta(element, positiondelta - rounddelta);
  144. UpdatePosition(element);
  145. }, Math.abs(animationduration/smoothdelta) );
  146. }
  147. else
  148. {
  149. scroll_timeout = setTimeout(function() {
  150. element.scrollTop = element.scrollTop + rounddelta;
  151. scrollpositiondelta(element, 0);
  152. }, animationduration);
  153.  
  154. }
  155.  
  156.  
  157. }
  158. else
  159. {
  160. scroll_timeout = setTimeout(function() {
  161. element.scrollTop = element.scrollTop + rounddelta;
  162. scrollpositiondelta(element, positiondelta - rounddelta);
  163. UpdatePosition(element);
  164. }, animationduration);
  165. }
  166. }
  167.  
  168.  
  169. function MouseScroll (e) {
  170.  
  171. var mul = 1;
  172. if (!WEBKIT || alternative_sensitivity_multiplier)
  173. mul = 40;
  174. var x = e.deltaX*mul;
  175. var y = e.deltaY*mul;
  176. if (mousemoved)
  177. {
  178. scrollfocus = UpdateFocus(x,y);
  179. mousemoved = false;
  180. }
  181. var positiondelta = 0;
  182. var lastscrolltop = 0;
  183.  
  184. var rolled = y;
  185. if (!canscroll(scrollfocus, rolled))
  186. {
  187. if (scrollfocus != document.documentElement)
  188. {
  189. scrollfocus = UpdateFocus(x,y);
  190. return false;
  191. }
  192. else
  193. {
  194. //console.log("true");
  195. return false;
  196. }
  197. }
  198. else
  199. {
  200. e.preventDefault();
  201. }
  202. positiondelta = scrollpositiondelta(scrollfocus);
  203. var direction = rolled/Math.abs(rolled);
  204. var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.09/sensitivity);
  205. positiondelta = positiondelta*1 + positiondeltadelta*1;
  206. scrollpositiondelta(scrollfocus, positiondelta)
  207.  
  208. clearTimeout(scroll_timeout);
  209. UpdatePosition(scrollfocus);
  210. return true;
  211. }
  212.  
  213. function canscroll(element, dir)
  214. {
  215. if (dir>0)
  216. {
  217. dir = 1;
  218. }
  219. if (dir<0)
  220. {
  221. dir = -1;
  222. }
  223. var checkradius = 3; //pixels to try scrolling
  224. var canscroll0 = false;
  225.  
  226. var scrollable = element;
  227.  
  228. var lastscrolltop = scrollable.scrollTop;
  229.  
  230. scrollable.scrollTop = lastscrolltop+dir*checkradius;
  231.  
  232. if (scrollable.scrollTop!=lastscrolltop)
  233. {
  234. canscroll0 = true;
  235. }
  236.  
  237. scrollable.scrollTop = lastscrolltop;
  238.  
  239. return canscroll0;
  240. }
  241. function scrollpositiondelta(element, newdelta)
  242. {
  243. //var target = //ss$(element);
  244. var target = element;
  245. var delta = 0;
  246. if (newdelta!=undefined)
  247. {
  248. //console.log(dir);
  249. var dir = 0;
  250. if (newdelta>0)
  251. {
  252. dir = 1;
  253. }
  254. if (newdelta<0)
  255. {
  256. dir = -1;
  257. }
  258. target.setAttribute("positiondelta", newdelta );
  259.  
  260. delta = newdelta;
  261. }
  262. else
  263. {
  264. var olddelta = target.getAttribute("positiondelta");
  265. if (olddelta!=undefined)
  266. {
  267. delta = olddelta;
  268. }
  269. }
  270. return delta*1;
  271. }
  272.  
  273. function UpdateFocus(x,y) {
  274. if (scrollfocus)
  275. {
  276. //scrollpositiondelta(scrollfocus, 0);
  277. //ss$(scrollfocus).stop();
  278. }
  279. var dir = y;
  280. var nodelist = document.querySelectorAll( ":hover" );
  281. if (WEBKIT)
  282. {
  283. //scrollfocus = //ss$('body');
  284. scrollfocus = document.body;
  285. }
  286. else
  287. {
  288. //scrollfocus = //ss$('html');
  289. scrollfocus = document.documentElement;
  290. }
  291. for (var i = nodelist.length-1; i >= 0 ; i--) {
  292. var newfocus = nodelist[i];
  293. if (canscroll(newfocus, dir) && hasscrollbars(newfocus))
  294. {
  295. scrollfocus = newfocus;
  296. return newfocus;
  297. }
  298. }
  299.  
  300. return scrollfocus;
  301. }
  302. /*ss$('html').bind({
  303. mousemove: function(e) {
  304. mousemoved = true;
  305. },
  306. mousedown: function(e) {
  307. if (DEBUG)
  308. {
  309. console.log(scrollfocus);
  310. }
  311. if (scrollfocus)
  312. {
  313. scrollpositiondelta(scrollfocus, 0);
  314. ////ss$(scrollfocus).stop();
  315. }
  316. scrollfocus = UpdateFocus(0,0);
  317. //console.log("click");
  318. }
  319. });
  320. */
  321. document.documentElement.addEventListener("wheel", function(e){
  322. MouseScroll(e);
  323. mousemoved = true;
  324. //console.log("scrolling");
  325. });
  326.  
  327. //WEBKIT = 'webkitRequestAnimationFrame' in window;
  328. WEBKIT = document.compatMode == 'CSS1Compat' || document.compatMode == "BackCompat";
  329. //console.log("window: " + window);
  330. console.log("Smoothscroll loaded! Webkit: " + WEBKIT);
  331. $smoothscroll$ = true;
  332. }
  333.  
  334. function LoadConfig()
  335. {
  336. smoothness = GM_getValue( 'smoothness', smoothness );
  337. sensitivity = GM_getValue( 'sensitivity', sensitivity );
  338. acceleration = GM_getValue( 'acceleration', acceleration );
  339. refreshrate = GM_getValue( 'refreshrate', refreshrate );
  340. //alternative_sesitivity_multiplier = GM_getValue( 'alternative_sesitivity_multiplier', alternative_sesitivity_multiplier );
  341. //console.log("Config for smoothscroll loaded!")
  342. }
  343.  
  344. function SaveConfig()
  345. {
  346. GM_setValue( 'smoothness', document.getElementById('ss-smoothness').value)
  347. GM_setValue( 'sensitivity', document.getElementById('ss-sensitivity').value)
  348. GM_setValue( 'acceleration', document.getElementById('ss-acceleration').value)
  349. GM_setValue( 'refreshrate', document.getElementById('ss-refreshrate').value)
  350. //console.log(document.getElementById('ss-alternative_sesitivity_multiplier').checked)
  351. //console.log("Config for smoothscroll saved!")
  352. }
  353.  
  354. function CloseConfig()
  355. {
  356. var configbar = document.getElementById("ss-configbar");
  357. configbar.style.display = 'none';
  358. }
  359.  
  360. function InitConfigmenu()
  361. {
  362. //console.log("Initiating smoothscroll config...");
  363. var configbar = document.createElement('div');
  364. configbar.setAttribute("id","ss-configbar");
  365. configbar.innerHTML = '<div style="display:block; width: 100%; height: auto; border: 0px solid #aaaaaa; background-color: grey;">Config page for smoothscroll (refresh page for changes to apply!) Made by: Creec Winceptor</div><div id="ss-config" style="margin:3px; display:block; width: auto; height: auto; border: 0px solid #554433;"><table style="width:auto;"><tr><td>Smoothness</td><td><input type="number" id="ss-smoothness" min="0" max="100" value="' + smoothness + '"></td><td> Smoothness factor value (how strong the smoothing effect is)</td></tr><tr><td>Sensitivity</td><td><input type="number" id="ss-sensitivity" min="0" max="100" value="' + sensitivity + '"></td><td> Scroll sensitivity (duh)</td></tr><tr><td>Acceleration</td><td><input type="number" id="ss-acceleration" min="0" max="100" value="' + acceleration + '"></td><td> Acceleration of continuous scroll action (saves your finger)</td></tr><tr><td>Refreshrate</td><td><input type="number" id="ss-refreshrate" min="1" max="100" value="' + refreshrate + '"></td><td>Refreshrate of scrollanimation (60Hz default)</td></tr></table></div><div style="width: 100%; height: auto; text-align: center; background-color: grey;"><input id="ss-save" type="button" value="Save config" style="width: 44%; height: auto; border: 0px solid #aaaaaa; margin: 3px"/><input id="ss-close" type="button" value="Close config" style="width: 44%; height: auto; border: 0px solid #aaaaaa; margin: 3px"/><div>';
  366. var configparent = document.getElementsByTagName("body")[0];
  367. configbar.style.width = '100%';
  368. configbar.style.display = 'none';
  369. configbar.style.position = 'absolute';
  370. configbar.style.zIndex = '9999';
  371. configbar.style.backgroundColor = 'white';
  372. configparent.insertBefore(configbar, configparent.childNodes[0]);
  373. document.getElementById("ss-close").onclick = function() {CloseConfig()};
  374. document.getElementById("ss-save").onclick = function() {SaveConfig()};
  375. }
  376.  
  377. function ConfigSmoothscroll()
  378. {
  379. if (typeof $smoothscroll$ == 'undefined'){
  380. alert("Smoothscroll is not running properly on this page!");
  381. return;
  382. }
  383.  
  384. var configbar = document.getElementById("ss-configbar");
  385. configbar.style.display = 'block';
  386. //ss$("html, body").animate({ scrollTop: 0 }, "slow");
  387. //console.log("opening config...");
  388. }
  389.  
  390. if (typeof $smoothscroll$ == 'undefined'){
  391. //console.log("Initiating smoothscroll...");
  392. InitSmoothscroll();
  393. GM_registerMenuCommand("Configurate smoothscroll", ConfigSmoothscroll);
  394. }
  395. else
  396. {
  397. console.log("Smoothscroll already loaded!");
  398. }