Smoothscroll

Smooth scrolling on pages using javascript and jquery

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

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