您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Smooth scrolling on pages using javascript
当前为
// ==UserScript== // @name Smoothscroll // @include http://* // @include https://* // @author Creec Winceptor // @description Smooth scrolling on pages using javascript // @namespace https://greasyfork.org/users/3167 // @run-at document-load // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @version 3.0 // ==/UserScript== if (window.top != window.self) //don't run on frames or iframes return; //DEFAULT SETTINGS HERE //DO NOT CHANGE ANYTHING HERE ANYMORE, USE SCRIPT COMMANDS -> CONFIGURE SMOOTHSCROLL //Smoothness factor value (how strong the smoothing effect is) //values: 1-(infinite) (default 1.00) var smoothness = 1; //Scroll sensitivity //values: anything? (default 1.00) var sensitivity = 1; //Acceleration sensitivity //values: anything? (default 1.50) var acceleration = 1; //Refreshrate setting //values: 30-144 (default = 60/72/120/144 = same as your monitor hz) var refreshrate = 60; //Alternative scrolling multiplier //values: true/false (try to set this to true if scrolling is too slow/doesn't work) var alternative_sensitivity_multiplier = false; //CODE STARTS HERE var DEBUG = false; var WEBKIT = false; //console.log("Loading smoothscroll..."); var baserefreshrate = 60; //DO NOT CHANGE THIS EVER if (smoothness>10) { smoothness = 10; } if (refreshrate <= 30 || refreshrate>144) { refreshrate = 144; } function InitSmoothscroll() { //LoadConfig(); //InitConfigmenu(); var startposition = false; var targetposition = 0; var position = 0; //var scrollfocus = //ss$('body'); var scrollfocus = document.body; var mousemoved = true; //var lastLoop = new Date; var nextLoop = 1; //var nextprint = lastLoop; var dynamicframedelay = 0; var dynamicrefreshrate = refreshrate; function fpscalcloop(animationduration) { var thisLoopDate = new Date; var thisLoop = thisLoopDate.getTime(); //var fpscalc = 1000 / (thisLoop - lastLoop + 1); //lastLoop = thisLoop; // var delay = thisLoop - nextLoop; //var fpscalc = 1000 / (thisLoop - nextLoop + 1); //refreshrate = refreshrate + (refreshrate0-refreshrate)*0.1; //refreshrate = Math.round(refreshrate); //animationduration = Math.round(1000/(refreshrate*3)); //console.log(animationduration); //var relativeratio = Math.round(51-smoothness/2)/100; //relativeratio = Math.round(1/(1+smoothness*baserefreshrate/refreshrate)*100)/100; // // if (animationduration>=0) { nextLoop = thisLoop+animationduration; framedelay = delay*refreshrate/1000; if (framedelay>1) { dynamicframedelay = dynamicframedelay + Math.ceil(framedelay); } else { if ( dynamicframedelay>1 && framedelay<1 ) { dynamicframedelay = dynamicframedelay - Math.ceil(dynamicframedelay/2); } } refreshrate = refreshrate*1; dynamicrefreshrate = Math.round( (refreshrate*refreshrate/(refreshrate+dynamicframedelay))*100 )/100; } else { nextLoop = thisLoop; } //console.log("dynamicframedelay: " + dynamicframedelay); //console.log("dynamicrefreshrate: " + dynamicrefreshrate); } function hasScrollBarVisible(element) { //return (document.documentElement.scrollHeight !== document.documentElement.clientHeight); // Get the computed style of the body element var cStyle = element.currentStyle||window.getComputedStyle(element, ""); // Check the overflow and overflowY properties for "auto" and "visible" values var scrollbar1 = cStyle.overflow == "scroll" || cStyle.overflowY == "scroll"; var scrollbar2 = cStyle.overflow == "auto" || cStyle.overflowY == "auto"; var scrollbar = scrollbar1 || scrollbar2; return scrollbar; } function hasscrollbars(scrollfocus) { var hasvisiblescrollbars = hasScrollBarVisible(scrollfocus); return hasvisiblescrollbars; /* var parentelement = //ss$(scrollfocus).parent(); if ( //ss$(parentelement)) { if (//ss$(parentelement).is("textarea") || //ss$(scrollfocus).is("textarea") || //ss$(parentelement).is("article") || //ss$(parentelement).is("article")) { return true; } else { if (//ss$(parentelement).hasClass( "yt-scrollbar" ) || //ss$(scrollfocus).hasClass( "yt-scrollbar" )) { return true; } return hasvisiblescrollbars; } } else { return hasvisiblescrollbars; } return false; */ } var scroll_timeout = null; function direction(number) { if (number>0) { return 1; } if (number<0) { return -1; } return 0; } function UpdatePosition(element) { //fpscalcloop(0); var basespeed = 2; var animationduration = Math.floor(1000/(dynamicrefreshrate)); //var relativeratio = Math.ceil( interpolation*( Math.pow(0.003*interpolation,smoothness)/dynamicrefreshrate *baserefreshrate )*1000000)/1000000; // //var relativeratio = Math.ceil( ( 0.5/dynamicrefreshrate *baserefreshrate )*1000000)/1000000; var relativeratio = 1-Math.pow( dynamicrefreshrate, -1/dynamicrefreshrate*smoothness*basespeed); var positiondelta = scrollpositiondelta(element); var dir = direction(positiondelta); //console.log("positiondelta:" + positiondelta); //var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio); // var smoothdelta = Math.abs(positiondelta*relativeratio); var rounddelta = Math.ceil(smoothdelta); //var smoothdelta = positiondelta*relativeratio; if ( rounddelta > 1 ) { element.scrollTop = element.scrollTop + rounddelta*dir; scrollpositiondelta(element, positiondelta - rounddelta*dir); scroll_timeout = setTimeout(function() { UpdatePosition(element); }, animationduration); fpscalcloop(animationduration); } else { if ( positiondelta*dir > 1 ) { element.scrollTop = element.scrollTop + dir; scrollpositiondelta(element, positiondelta - dir); scroll_timeout = setTimeout(function() { UpdatePosition(element); }, (animationduration/smoothdelta)); } else { element.scrollTop = element.scrollTop + rounddelta*dir; scrollpositiondelta(element, 0); //scroll_timeout = setTimeout(function() { //}, (animationduration/smoothdelta)); } fpscalcloop( (animationduration/smoothdelta) ); } } function MouseScroll (e) { var mul = 1; if (!WEBKIT || alternative_sensitivity_multiplier) mul = 40; var x = e.deltaX*mul; var y = e.deltaY*mul; scrollfocus = UpdateFocus(e); /*if (mousemoved) { scrollfocus = UpdateFocus(x,y); mousemoved = false; }*/ var positiondelta = 0; var lastscrolltop = 0; var rolled = y; if (!canscroll(scrollfocus, rolled)) { if (scrollfocus != document.documentElement) { //scrollfocus = UpdateFocus(e); return false; } else { //console.log("true"); return false; } } else { if (e.defaultPrevented) { return true; } else { e.preventDefault(); } } positiondelta = scrollpositiondelta(scrollfocus); var direction = rolled/Math.abs(rolled); //var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.2); //var positiondeltadelta = Math.round(Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.2); var positiondeltadelta = rolled*sensitivity; var positiondeltacceleration = Math.sqrt(Math.abs(positiondelta/positiondeltadelta*acceleration)); //console.log("positiondelta: "+positiondelta+" positiondeltadelta: " + positiondeltadelta + " positiondeltacceleration: " + positiondeltacceleration); positiondelta = Math.round(positiondelta*1 + positiondeltadelta*(1+positiondeltacceleration) ); scrollpositiondelta(scrollfocus, positiondelta) clearTimeout(scroll_timeout); fpscalcloop(-1); UpdatePosition(scrollfocus); //console.log(e); return true; } function canscroll(element, dir) { if (dir>0) { dir = 1; } if (dir<0) { dir = -1; } var checkradius = 3; //pixels to try scrolling var canscroll0 = false; var scrollable = element; var lastscrolltop = scrollable.scrollTop; scrollable.scrollTop = lastscrolltop+dir*checkradius; if (scrollable.scrollTop!=lastscrolltop) { canscroll0 = true; } scrollable.scrollTop = lastscrolltop; return canscroll0; } function scrollpositiondelta(element, newdelta) { var target = element; var delta = 0; if (newdelta!=undefined) { target.positiondelta = newdelta; delta = newdelta; } else { var olddelta = target.positiondelta; if (olddelta!=undefined) { delta = olddelta; } } return delta*1; } function UpdateFocus(e) { var x = e.deltaX; var y = e.deltaY; if (scrollfocus) { //scrollpositiondelta(scrollfocus, 0); } var dir = y; var nodelist = document.querySelectorAll( ":hover" ); if (WEBKIT) { //scrollfocus = //ss$('body'); scrollfocus = document.body; } else { //scrollfocus = //ss$('html'); scrollfocus = document.documentElement; } for (var i = nodelist.length-1; i >= 0 ; i--) { var newfocus = nodelist[i]; if (canscroll(newfocus, dir) && hasscrollbars(newfocus)) { scrollfocus = newfocus; return newfocus; } } return scrollfocus; } document.documentElement.addEventListener("wheel", function(e){ MouseScroll(e); }); document.documentElement.addEventListener("mousedown", function(e){ if (scrollfocus) { scrollpositiondelta(scrollfocus, 0); } }); /* document.documentElement.addEventListener("mousemove", function(e){ mousemoved = true; });*/ //WEBKIT = 'webkitRequestAnimationFrame' in window; WEBKIT = document.compatMode == 'CSS1Compat' || document.compatMode == "BackCompat"; //console.log("window: " + window); console.log("Smoothscroll loaded! Webkit: " + WEBKIT); $smoothscroll$ = true; } function LoadConfig() { smoothness = GM_getValue( 'smoothness', smoothness ); sensitivity = GM_getValue( 'sensitivity', sensitivity ); acceleration = GM_getValue( 'acceleration', acceleration ); refreshrate = GM_getValue( 'refreshrate', refreshrate ); //alternative_sesitivity_multiplier = GM_getValue( 'alternative_sesitivity_multiplier', alternative_sesitivity_multiplier ); //console.log("Config for smoothscroll loaded!") } function SaveConfig() { GM_setValue( 'smoothness', document.getElementById('ss-smoothness').value) GM_setValue( 'sensitivity', document.getElementById('ss-sensitivity').value) GM_setValue( 'acceleration', document.getElementById('ss-acceleration').value) GM_setValue( 'refreshrate', document.getElementById('ss-refreshrate').value) //console.log(document.getElementById('ss-alternative_sesitivity_multiplier').checked) console.log("Config for smoothscroll saved!") location.reload(); } function CloseConfig() { var configbar = document.getElementById("ss-configbar"); configbar.style.display = 'none'; } function InitConfigmenu() { //console.log("Initiating smoothscroll config..."); var configbar = document.createElement('div'); configbar.setAttribute("id","ss-configbar"); //<tr><td>Sensitivity</td><td><input type="number" id="ss-sensitivity" min="0" max="100" value="' + sensitivity + '"></td><td> Scroll sensitivity (duh)</td></tr> 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>'; var configparent = document.documentElement; configbar.style.width = '100%'; configbar.style.display = 'none'; configbar.style.position = 'absolute'; configbar.style.zIndex = '9999'; configbar.style.backgroundColor = 'white'; configparent.insertBefore(configbar, configparent.childNodes[0]); document.getElementById("ss-close").onclick = function() {CloseConfig()}; document.getElementById("ss-save").onclick = function() {SaveConfig()}; } var ConfigSmoothscroll = function() { console.log("opening"); if (typeof $smoothscroll$ == 'undefined'){ alert("Smoothscroll is not running properly on this page!"); return; } var configbar = document.getElementById("ss-configbar"); configbar.style.display = 'block'; window.scrollTo(0, 0); //ss$("html, body").animate({ scrollTop: 0 }, "slow"); console.log("opening config..."); } if (typeof $smoothscroll$ == 'undefined'){ //console.log("Initiating smoothscroll..."); InitSmoothscroll(); GM_registerMenuCommand("Smoothscroll config", ConfigSmoothscroll ); } else { console.log("Smoothscroll already loaded!"); }