Smoothscroll

Smooth scrolling on pages using javascript and jquery

目前为 2016-11-06 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Smoothscroll
  3. // @include http*
  4. // @author Creec Winceptor
  5. // @description Smooth scrolling on pages using javascript and jquery
  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.3
  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. if (e.defaultPrevented)
  201. {
  202. return true;
  203. }
  204. else
  205. {
  206. e.preventDefault();
  207. }
  208. }
  209. positiondelta = scrollpositiondelta(scrollfocus);
  210. var direction = rolled/Math.abs(rolled);
  211. var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.09/sensitivity);
  212. positiondelta = positiondelta*1 + positiondeltadelta*1;
  213. scrollpositiondelta(scrollfocus, positiondelta)
  214.  
  215. clearTimeout(scroll_timeout);
  216. UpdatePosition(scrollfocus);
  217. //console.log(e);
  218. return true;
  219. }
  220.  
  221. function canscroll(element, dir)
  222. {
  223. if (dir>0)
  224. {
  225. dir = 1;
  226. }
  227. if (dir<0)
  228. {
  229. dir = -1;
  230. }
  231. var checkradius = 3; //pixels to try scrolling
  232. var canscroll0 = false;
  233.  
  234. var scrollable = element;
  235.  
  236. var lastscrolltop = scrollable.scrollTop;
  237.  
  238. scrollable.scrollTop = lastscrolltop+dir*checkradius;
  239.  
  240. if (scrollable.scrollTop!=lastscrolltop)
  241. {
  242. canscroll0 = true;
  243. }
  244.  
  245. scrollable.scrollTop = lastscrolltop;
  246.  
  247. return canscroll0;
  248. }
  249. function scrollpositiondelta(element, newdelta)
  250. {
  251. //var target = //ss$(element);
  252. var target = element;
  253. var delta = 0;
  254. if (newdelta!=undefined)
  255. {
  256. //console.log(dir);
  257. var dir = 0;
  258. if (newdelta>0)
  259. {
  260. dir = 1;
  261. }
  262. if (newdelta<0)
  263. {
  264. dir = -1;
  265. }
  266. target.setAttribute("positiondelta", newdelta );
  267.  
  268. delta = newdelta;
  269. }
  270. else
  271. {
  272. var olddelta = target.getAttribute("positiondelta");
  273. if (olddelta!=undefined)
  274. {
  275. delta = olddelta;
  276. }
  277. }
  278. return delta*1;
  279. }
  280.  
  281. function UpdateFocus(x,y) {
  282. if (scrollfocus)
  283. {
  284. //scrollpositiondelta(scrollfocus, 0);
  285. //ss$(scrollfocus).stop();
  286. }
  287. var dir = y;
  288. var nodelist = document.querySelectorAll( ":hover" );
  289. if (WEBKIT)
  290. {
  291. //scrollfocus = //ss$('body');
  292. scrollfocus = document.body;
  293. }
  294. else
  295. {
  296. //scrollfocus = //ss$('html');
  297. scrollfocus = document.documentElement;
  298. }
  299. for (var i = nodelist.length-1; i >= 0 ; i--) {
  300. var newfocus = nodelist[i];
  301. if (canscroll(newfocus, dir) && hasscrollbars(newfocus))
  302. {
  303. scrollfocus = newfocus;
  304. return newfocus;
  305. }
  306. }
  307.  
  308. return scrollfocus;
  309. }
  310. /*ss$('html').bind({
  311. mousemove: function(e) {
  312. mousemoved = true;
  313. },
  314. mousedown: function(e) {
  315. if (DEBUG)
  316. {
  317. console.log(scrollfocus);
  318. }
  319. if (scrollfocus)
  320. {
  321. scrollpositiondelta(scrollfocus, 0);
  322. ////ss$(scrollfocus).stop();
  323. }
  324. scrollfocus = UpdateFocus(0,0);
  325. //console.log("click");
  326. }
  327. });
  328. */
  329. document.documentElement.addEventListener("wheel", function(e){
  330. MouseScroll(e);
  331. mousemoved = true;
  332. //console.log("scrolling");
  333. });
  334.  
  335. //WEBKIT = 'webkitRequestAnimationFrame' in window;
  336. WEBKIT = document.compatMode == 'CSS1Compat' || document.compatMode == "BackCompat";
  337. //console.log("window: " + window);
  338. console.log("Smoothscroll loaded! Webkit: " + WEBKIT);
  339. $smoothscroll$ = true;
  340. }
  341.  
  342. function LoadConfig()
  343. {
  344. smoothness = GM_getValue( 'smoothness', smoothness );
  345. sensitivity = GM_getValue( 'sensitivity', sensitivity );
  346. acceleration = GM_getValue( 'acceleration', acceleration );
  347. refreshrate = GM_getValue( 'refreshrate', refreshrate );
  348. //alternative_sesitivity_multiplier = GM_getValue( 'alternative_sesitivity_multiplier', alternative_sesitivity_multiplier );
  349. //console.log("Config for smoothscroll loaded!")
  350. }
  351.  
  352. function SaveConfig()
  353. {
  354. GM_setValue( 'smoothness', document.getElementById('ss-smoothness').value)
  355. GM_setValue( 'sensitivity', document.getElementById('ss-sensitivity').value)
  356. GM_setValue( 'acceleration', document.getElementById('ss-acceleration').value)
  357. GM_setValue( 'refreshrate', document.getElementById('ss-refreshrate').value)
  358. //console.log(document.getElementById('ss-alternative_sesitivity_multiplier').checked)
  359. //console.log("Config for smoothscroll saved!")
  360. }
  361.  
  362. function CloseConfig()
  363. {
  364. var configbar = document.getElementById("ss-configbar");
  365. configbar.style.display = 'none';
  366. }
  367.  
  368. function InitConfigmenu()
  369. {
  370. //console.log("Initiating smoothscroll config...");
  371. var configbar = document.createElement('div');
  372. configbar.setAttribute("id","ss-configbar");
  373. 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>';
  374. var configparent = document.getElementsByTagName("body")[0];
  375. configbar.style.width = '100%';
  376. configbar.style.display = 'none';
  377. configbar.style.position = 'absolute';
  378. configbar.style.zIndex = '9999';
  379. configbar.style.backgroundColor = 'white';
  380. configparent.insertBefore(configbar, configparent.childNodes[0]);
  381. document.getElementById("ss-close").onclick = function() {CloseConfig()};
  382. document.getElementById("ss-save").onclick = function() {SaveConfig()};
  383. }
  384.  
  385. function ConfigSmoothscroll()
  386. {
  387. if (typeof $smoothscroll$ == 'undefined'){
  388. alert("Smoothscroll is not running properly on this page!");
  389. return;
  390. }
  391.  
  392. var configbar = document.getElementById("ss-configbar");
  393. configbar.style.display = 'block';
  394. //ss$("html, body").animate({ scrollTop: 0 }, "slow");
  395. //console.log("opening config...");
  396. }
  397.  
  398. if (typeof $smoothscroll$ == 'undefined'){
  399. //console.log("Initiating smoothscroll...");
  400. InitSmoothscroll();
  401. GM_registerMenuCommand("Configurate smoothscroll", ConfigSmoothscroll);
  402. }
  403. else
  404. {
  405. console.log("Smoothscroll already loaded!");
  406. }