Smoothscroll

Smooth scrolling on pages using javascript and jquery

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

  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.4.1
  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) (default 1.00)
  24. var smoothness = 1;
  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>10)
  54. {
  55. smoothness = 10;
  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( ( Math.pow(0.01,smoothness)*refreshrate/baserefreshrate )*1000000)/1000000;
  127. var positiondelta = scrollpositiondelta(element);
  128. var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio)/interpolation;
  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. scroll_timeout = setTimeout(function() {
  140. element.scrollTop = element.scrollTop + rounddelta;
  141. scrollpositiondelta(element, positiondelta - rounddelta);
  142. UpdatePosition(element);
  143. }, animationduration);
  144. }
  145. else
  146. {
  147. if (Math.abs( positiondelta ) > 1 )
  148. {
  149. scroll_timeout = setTimeout(function() {
  150. element.scrollTop = element.scrollTop + rounddelta;
  151. scrollpositiondelta(element, positiondelta - rounddelta);
  152. UpdatePosition(element);
  153. }, Math.abs(animationduration/smoothdelta) );
  154. }
  155. else
  156. {
  157. scroll_timeout = setTimeout(function() {
  158. element.scrollTop = element.scrollTop + rounddelta;
  159. scrollpositiondelta(element, 0);
  160. }, Math.abs(animationduration/smoothdelta));
  161.  
  162. }
  163. }
  164. }
  165.  
  166.  
  167. function MouseScroll (e) {
  168.  
  169. var mul = 1;
  170. if (!WEBKIT || alternative_sensitivity_multiplier)
  171. mul = 40;
  172. var x = e.deltaX*mul;
  173. var y = e.deltaY*mul;
  174. //if (mousemoved)
  175. //{
  176. scrollfocus = UpdateFocus(x,y);
  177. //mousemoved = false;
  178. //}
  179. var positiondelta = 0;
  180. var lastscrolltop = 0;
  181.  
  182. var rolled = y;
  183. if (!canscroll(scrollfocus, rolled))
  184. {
  185. if (scrollfocus != document.documentElement)
  186. {
  187. scrollfocus = UpdateFocus(x,y);
  188. return false;
  189. }
  190. else
  191. {
  192. //console.log("true");
  193. return false;
  194. }
  195. }
  196. else
  197. {
  198. if (e.defaultPrevented)
  199. {
  200. return true;
  201. }
  202. else
  203. {
  204. e.preventDefault();
  205. }
  206. }
  207. positiondelta = scrollpositiondelta(scrollfocus);
  208. var direction = rolled/Math.abs(rolled);
  209. var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.2);
  210. positiondelta = positiondelta*1 + positiondeltadelta*1;
  211. scrollpositiondelta(scrollfocus, positiondelta)
  212.  
  213. clearTimeout(scroll_timeout);
  214. UpdatePosition(scrollfocus);
  215. //console.log(e);
  216. return true;
  217. }
  218.  
  219. function canscroll(element, dir)
  220. {
  221. if (dir>0)
  222. {
  223. dir = 1;
  224. }
  225. if (dir<0)
  226. {
  227. dir = -1;
  228. }
  229. var checkradius = 3; //pixels to try scrolling
  230. var canscroll0 = false;
  231.  
  232. var scrollable = element;
  233.  
  234. var lastscrolltop = scrollable.scrollTop;
  235.  
  236. scrollable.scrollTop = lastscrolltop+dir*checkradius;
  237.  
  238. if (scrollable.scrollTop!=lastscrolltop)
  239. {
  240. canscroll0 = true;
  241. }
  242.  
  243. scrollable.scrollTop = lastscrolltop;
  244.  
  245. return canscroll0;
  246. }
  247. function scrollpositiondelta(element, newdelta)
  248. {
  249. //var target = //ss$(element);
  250. var target = element;
  251. var delta = 0;
  252. if (newdelta!=undefined)
  253. {
  254. //console.log(dir);
  255. var dir = 0;
  256. if (newdelta>0)
  257. {
  258. dir = 1;
  259. }
  260. if (newdelta<0)
  261. {
  262. dir = -1;
  263. }
  264. target.setAttribute("positiondelta", newdelta );
  265.  
  266. delta = newdelta;
  267. }
  268. else
  269. {
  270. var olddelta = target.getAttribute("positiondelta");
  271. if (olddelta!=undefined)
  272. {
  273. delta = olddelta;
  274. }
  275. }
  276. return delta*1;
  277. }
  278.  
  279. function UpdateFocus(x,y) {
  280. if (scrollfocus)
  281. {
  282. //scrollpositiondelta(scrollfocus, 0);
  283. //ss$(scrollfocus).stop();
  284. }
  285. var dir = y;
  286. var nodelist = document.querySelectorAll( ":hover" );
  287. if (WEBKIT)
  288. {
  289. //scrollfocus = //ss$('body');
  290. scrollfocus = document.body;
  291. }
  292. else
  293. {
  294. //scrollfocus = //ss$('html');
  295. scrollfocus = document.documentElement;
  296. }
  297. for (var i = nodelist.length-1; i >= 0 ; i--) {
  298. var newfocus = nodelist[i];
  299. if (canscroll(newfocus, dir) && hasscrollbars(newfocus))
  300. {
  301. scrollfocus = newfocus;
  302. return newfocus;
  303. }
  304. }
  305.  
  306. return scrollfocus;
  307. }
  308. /*ss$('html').bind({
  309. mousemove: function(e) {
  310. mousemoved = true;
  311. },
  312. mousedown: function(e) {
  313. if (DEBUG)
  314. {
  315. console.log(scrollfocus);
  316. }
  317. if (scrollfocus)
  318. {
  319. scrollpositiondelta(scrollfocus, 0);
  320. ////ss$(scrollfocus).stop();
  321. }
  322. scrollfocus = UpdateFocus(0,0);
  323. //console.log("click");
  324. }
  325. });
  326. */
  327. document.documentElement.addEventListener("wheel", function(e){
  328. MouseScroll(e);
  329. mousemoved = true;
  330. //console.log("scrolling");
  331. });
  332.  
  333. //WEBKIT = 'webkitRequestAnimationFrame' in window;
  334. WEBKIT = document.compatMode == 'CSS1Compat' || document.compatMode == "BackCompat";
  335. //console.log("window: " + window);
  336. console.log("Smoothscroll loaded! Webkit: " + WEBKIT);
  337. $smoothscroll$ = true;
  338. }
  339.  
  340. function LoadConfig()
  341. {
  342. smoothness = GM_getValue( 'smoothness', smoothness );
  343. sensitivity = GM_getValue( 'sensitivity', sensitivity );
  344. acceleration = GM_getValue( 'acceleration', acceleration );
  345. refreshrate = GM_getValue( 'refreshrate', refreshrate );
  346. //alternative_sesitivity_multiplier = GM_getValue( 'alternative_sesitivity_multiplier', alternative_sesitivity_multiplier );
  347. //console.log("Config for smoothscroll loaded!")
  348. }
  349.  
  350. function SaveConfig()
  351. {
  352. GM_setValue( 'smoothness', document.getElementById('ss-smoothness').value)
  353. GM_setValue( 'sensitivity', document.getElementById('ss-sensitivity').value)
  354. GM_setValue( 'acceleration', document.getElementById('ss-acceleration').value)
  355. GM_setValue( 'refreshrate', document.getElementById('ss-refreshrate').value)
  356. //console.log(document.getElementById('ss-alternative_sesitivity_multiplier').checked)
  357. console.log("Config for smoothscroll saved!")
  358. }
  359.  
  360. function CloseConfig()
  361. {
  362. var configbar = document.getElementById("ss-configbar");
  363. configbar.style.display = 'none';
  364. }
  365.  
  366. function InitConfigmenu()
  367. {
  368. //console.log("Initiating smoothscroll config...");
  369. var configbar = document.createElement('div');
  370. configbar.setAttribute("id","ss-configbar");
  371. //<tr><td>Sensitivity</td><td><input type="number" id="ss-sensitivity" min="0" max="100" value="' + sensitivity + '"></td><td> Scroll sensitivity (duh)</td></tr>
  372. 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>';
  373. var configparent = document.getElementsByTagName("body")[0];
  374. configbar.style.width = '100%';
  375. configbar.style.display = 'none';
  376. configbar.style.position = 'absolute';
  377. configbar.style.zIndex = '9999';
  378. configbar.style.backgroundColor = 'white';
  379. configparent.insertBefore(configbar, configparent.childNodes[0]);
  380. document.getElementById("ss-close").onclick = function() {CloseConfig()};
  381. document.getElementById("ss-save").onclick = function() {SaveConfig()};
  382. }
  383.  
  384. function ConfigSmoothscroll()
  385. {
  386. if (typeof $smoothscroll$ == 'undefined'){
  387. alert("Smoothscroll is not running properly on this page!");
  388. return;
  389. }
  390.  
  391. var configbar = document.getElementById("ss-configbar");
  392. configbar.style.display = 'block';
  393. //ss$("html, body").animate({ scrollTop: 0 }, "slow");
  394. //console.log("opening config...");
  395. }
  396.  
  397. if (typeof $smoothscroll$ == 'undefined'){
  398. //console.log("Initiating smoothscroll...");
  399. InitSmoothscroll();
  400. GM_registerMenuCommand("Configurate smoothscroll", ConfigSmoothscroll);
  401. }
  402. else
  403. {
  404. console.log("Smoothscroll already loaded!");
  405. }