Smoothscroll

Smooth scrolling on pages using javascript and jquery

目前为 2016-05-24 提交的版本。查看 最新版本

// ==UserScript==
// @name Smoothscroll
// @include     http*
// @author       Creec Winceptor
// @description  Smooth scrolling on pages using javascript and jquery
// @namespace https://gf.qytechs.cn/users/3167
// @run-at document-load
// @grant    GM_info
// @grant         unsafeWindow
// @version 0.0.1.20160524014511
// ==/UserScript==






//SETTINGS HERE

//Smoothness factor value (how strong the smoothing effect is)
//values: 1-(infinite) (default = 50)
var smoothness = 30;


//Scroll sensitivity
//values: anything? (default 1.00)
var sensitivity = 1.00;


//Acceleration sensitivity
//values: anything? (default 1.00)
var acceleration = 1.00;


//Refreshrate setting
//values: 30-144 (default = 60/72/120/144 = same as your monitor hz)
var baserefreshrate = 72;


//Alternative scrolling multiplier
//values: true/false (try to set this to true if scrolling is too slow/doesn't work)
var alternative_sesitivity_multiplier = false;


var minimal_jquery_version = 200;



var DEBUG = false;

//CODE STARTS HERE
if (window.top != window.self)  //don't run on frames or iframes
    return;



if (smoothness>100)
{
	smoothness = 100;
}

if (baserefreshrate <= 30 || baserefreshrate>144)
{
	baserefreshrate = 144;
}
refreshrate = baserefreshrate;

var animationduration = Math.round(1000/refreshrate);
//var relativeratio = Math.round(51-smoothness/2)/100;
var relativeratio = Math.round(1/(1+smoothness)*100)/100;
//var relativeratio = relativeratio;



var lastLoop = new Date;
//var lastrefreshrate = 0;
function gameLoop() { 
	var thisLoop = new Date;
    var refreshrate0 = 1000 / (thisLoop - lastLoop + 1);
    lastLoop = thisLoop;
	
	refreshrate = refreshrate + (refreshrate0-refreshrate)*0.01;
	refreshrate = Math.round(refreshrate);
	
	if (DEBUG)
	{
		console.log(refreshrate);
	}
	
	animationduration = Math.round(1000/(refreshrate));
	//var relativeratio = Math.round(51-smoothness/2)/100;
	relativeratio = Math.round(1/(1+smoothness*refreshrate/baserefreshrate)*100)/100;
}
gameLoop();


function InitSmoothscroll()
{

var startposition = false;
var targetposition = 0;
var position = 0;

var scrollfocus = $0('body');
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);
	var parentelement = $0(scrollfocus).parent();
	if ( $0(parentelement))
	{
		//if ($0(parentelement).is("textarea") || $0(scrollfocus).is("textarea"))
		if ($0(parentelement).is("textarea") || $0(scrollfocus).is("textarea") || $0(parentelement).is("article") || $0(parentelement).is("article"))
		{
			return true;
		}
		else
		{
			if ($0(parentelement).hasClass( "yt-scrollbar" ) || $0(scrollfocus).hasClass( "yt-scrollbar" ))
			{
				return true;
			}
			return hasvisiblescrollbars;
		}
	}
	else
	{
		//scrollfocus = $0('body');
		//maxposition = $0(scrollfocus).height();
		return hasvisiblescrollbars;
	}
	return false;
}

function UpdatePosition(element)
{
	gameLoop();
	
	var positiondelta = $0(element)[0].getAttribute( "positiondelta" );
	//var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio);
	
	var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio);
	
	if (positiondelta<0)
	{
		smoothdelta = smoothdelta*(-1);
	}
	
	//var relative = position - $0(element).scrollTop();
	//console.log("smoothdelta:" + smoothdelta);
	
	if (Math.abs( (positiondelta-smoothdelta)) <= 1 )
	{
		$0(element).stop();
		$0(element).animate({
			scrollTop: '+=' + Math.round(positiondelta)
		}, animationduration, "linear", function() {
			$0(element).attr( "positiondelta",0 );
			$0(element)[0].setAttribute( "positiondelta",0 );
			if (DEBUG)
			{
				$0(element).css( "border", "1px solid red" );
			}
		});
	}
	else
	{
		
		$0(element).stop();
		$0(element).animate({
			scrollTop: '+=' + Math.round(smoothdelta)
		}, animationduration, "linear", function() {
			$0(element).attr( "positiondelta",positiondelta-smoothdelta );
			$0(element)[0].setAttribute("positiondelta",positiondelta-smoothdelta );
			UpdatePosition(element);
			if (DEBUG)
			{
				$0(element).css( "border", "1px solid red" );
			}
		});
	}
}


 function MouseScroll (x,y,e) {
	 scrollfocus = UpdateFocus(x,y);
	
	 var positiondelta = 0;
	 var lastscrolltop = 0;

	 var parentelement = $0(scrollfocus).parent();
	 if ( $0(parentelement))
	 {
		 if ($0(parentelement).is("textarea") || $0(scrollfocus).is("textarea"))
		 {
			 //return true;
		 }
		 else
		 {
			 if ( $0(parentelement).height() < $0(scrollfocus).height())
			 {
				 //maxposition = $0(scrollfocus).height() - $0(parentelement).height();
			 }
			 else
			 {
				 if ($0(scrollfocus).height()==0)
				 {
					 //scrollfocus = $0('body');
					 //maxposition = $0(scrollfocus).height();
				 }

				 //scrollfocus = $0('body');
				 //return MouseScroll (event);
				 //return true;
			 }
		 }
	 }
	 else
	 {
		 scrollfocus = $0('body');
		 //maxposition = $0(scrollfocus).height();
	 }
	 
	 var rolled = y;
	 
	 //console.log("rolled: " + rolled);
	
	 //if ($0(scrollfocus).data("positiondelta" )==undefined)
	 //$embellishment.data("embellishmentid",1)
	 if ($0(scrollfocus)[0].getAttribute("positiondelta")==undefined)
		 
		 {
			 positiondelta = 0;
			 //console.log("positiondelta: undefined");
		 }
	 else
		 {
			 positiondelta = $0(scrollfocus)[0].getAttribute("positiondelta");
			 //console.log("positiondelta: " + positiondelta);
		 }
	 positiondelta = positiondelta*1;
	 
	 	var lastscrolltop = $0(scrollfocus).scrollTop();
	 	$0(scrollfocus).scrollTop(lastscrolltop+rolled);
	 	if ($0(scrollfocus).scrollTop()==lastscrolltop)
		{
			if (!$0(scrollfocus).is("body"))
			{
				focus = parentelement;
				//focus = UpdateFocus(event);
				//return MouseScroll (event);
				//console.log("false");
				return false;
			}
			else
			{
				//console.log("true");
				return false;
			}
		}
	 	else
		{
			e.preventDefault();
		}
	    $0(scrollfocus).scrollTop(lastscrolltop);
	 
	 var direction = rolled/Math.abs(rolled);
	 //var positiondeltadelta = rolled*sensitivity + Math.sqrt(Math.abs(positiondelta/rolled))*acceleration*rolled;
	 
	 //var positiondeltadelta = rolled*(sensitivity+Math.sqrt(Math.abs(positiondelta))*acceleration);
	 //
	 var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.03/sensitivity);
	 
	 positiondelta = positiondelta + positiondeltadelta;
	
	 $0(scrollfocus)[0].setAttribute("positiondelta",positiondelta );
	 
	 
	 UpdatePosition($0(scrollfocus));
	 
	 //element.innerHTML = "";
	 //console.log("pos:" + position);
	 //event.preventDefault();
	 return true;
 }

 function canscroll(element, dir)
{
	var scrollable = $0(element);
	var lastscrolltop = $0(scrollable).scrollTop();
	$0(scrollable).scrollTop(lastscrolltop+dir);
	if ($0(scrollable).scrollTop()==lastscrolltop)
	{
		$0(scrollable).scrollTop(lastscrolltop);
		return false;
	}
	else
	{
		$0(scrollable).scrollTop(lastscrolltop);
		return true;
	}
	
}
function UpdateFocus(x,y) {
	 /*var dir = 0;
	 if ('wheelDelta' in event) {
		 dir = event.wheelDelta;
	 }
	 else {  // Firefox
		 // The measurement units of the detail and wheelDelta properties are different.
		 dir = event.detail*(-120);
	 }*/
	var dir = y;
	//console.log(dir);
	 //dir = dir*(-1);
	 //
	 	var nodelist = document.querySelectorAll( ":hover" );
		$0(nodelist).stop();
	 	scrollfocus = $0('body');
	 	for (var i = nodelist.length-1; i >= 0; i--) { 
				//var parent = nodelist[i-1];
			  var newfocus = nodelist[i];
				if (DEBUG)
				{
					$0(newfocus).css( "border", "1px solid blue" );
					//var debugtimer = setTimeout(function(){ $0(newfocus).css( "border", "0px solid white" ); }, 1000);
				}
				//if ($0(newfocus).hasScrollBar3() && hasScrollBarVisible(newfocus) && canscroll(newfocus, dir) && hasscrollbars(newfocus))
				if (canscroll(newfocus, dir) && hasscrollbars(newfocus))
				{
					scrollfocus = $0(newfocus);
					return newfocus;
				}
 		}

	 return scrollfocus;
 }
	
		$0('body').bind({
			/*
			 mousewheel: function(e) {
			if (DEBUG)
			{
				console.log(scrollfocus);
			}
			  console.log("scrolling");
			  MouseScroll(e.originalEvent);
		  },
		  */
			
		  mousedown: function(e) {
			 if (DEBUG)
			{
				console.log(scrollfocus);
			}
			  if (scrollfocus)
			{
			  $0(scrollfocus)[0].setAttribute( "positiondelta",0 );
			  $0(scrollfocus).stop();
			}
				//scrollfocus = UpdateFocus(e.originalEvent);
			  //console.log("click");
		  }
		});
//Init(window);

(function(window,document) {

    var prefix = "", _addEventListener, onwheel, support;

    // detect event model
    if ( window.addEventListener ) {
        _addEventListener = "addEventListener";
    } else {
        _addEventListener = "attachEvent";
        prefix = "on";
    }

    // detect available wheel event
    support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
              document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
              "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

    window.addWheelListener = function( elem, callback, useCapture ) {
        _addWheelListener( elem, support, callback, useCapture );

        // handle MozMousePixelScroll in older Firefox
        if( support == "DOMMouseScroll" ) {
            _addWheelListener( elem, "MozMousePixelScroll", callback, useCapture );
        }
    };

    function _addWheelListener( elem, eventName, callback, useCapture ) {
        elem[ _addEventListener ]( prefix + eventName, support == "wheel" ? callback : function( originalEvent ) {
            !originalEvent && ( originalEvent = window.event );

            // create a normalized event object
            var event = {
                // keep a ref to the original event object
                originalEvent: originalEvent,
                target: originalEvent.target || originalEvent.srcElement,
                type: "wheel",
                deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
                deltaX: 0,
                deltaZ: 0,
                preventDefault: function() {
                    originalEvent.preventDefault ?
                        originalEvent.preventDefault() :
                        originalEvent.returnValue = false;
                }
            };
            
            // calculate deltaY (and deltaX) according to the event
            if ( support == "mousewheel" ) {
                event.deltaY = - 1/40 * originalEvent.wheelDelta;
                // Webkit also support wheelDeltaX
                originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
            } else {
                event.deltaY = originalEvent.detail;
            }

            // it's time to fire the callback
            return callback( event );

        }, useCapture || false );
    }

})(window,document);
	
addWheelListener( window, function( e ) { 
	var mul = 1;
	if (alternative_sesitivity_multiplier)
		mul = 40;
	//console.log( e.deltaY ); 
	MouseScroll(e.deltaX*mul,e.deltaY*mul, e);
});	

	
console.log("Smoothscroll initiated!");
}


var JQUERY = false;
var OWNJQUERY = false;
var OLDJQUERY = false;

//max retries
var r_max = 10;
var r_count = 0;

function Init() {
  //if (typeof jQuery == 'function')  {  
  //if (typeof jQuery == 'undefined' || typeof $ == 'undefined' ) 
  JQUERY = true;
  if (typeof $ == 'undefined' ) 
  {
    JQUERY = false;
  }
  OWNJQUERY = true;
  if (typeof $0 == 'undefined' ) 
  {
    OWNJQUERY = false;
  }
  if (!OWNJQUERY){
    if (JQUERY) {
      var versiontable = $.fn.jquery.split('.');
      var version = 0;
      for (var i = versiontable.length-1; i >= 0; i--) { 
        var power = versiontable.length-i;
        version += Math.pow(10,power-1)*versiontable[i];
      }

      if (version<=minimal_jquery_version)
      {
        console.log("Page jQuery OLD! Version: " + version);
        if (typeof old$ == 'undefined') {
          console.log("Saving old jQuery...");  
          old$ = $;
          oldjQuery = jQuery;
          
          OLDJQUERY = true;
        }
      }
      else
      {
        $0 = $;
        OWNJQUERY = true;
      }
    }
    else
    {
      console.log("Page jQuery Missing!");
    }
  }
  if (!OWNJQUERY)
  {
    console.log("Loading new jQuery...");  

    //this.$ = this.jQuery = jQuery.noConflict(true);
    //var $ = jQuery.noConflict();

    //this.$ = this.jQuery = jQuery.noConflict(true);


    var filename = "https://code.jquery.com/jquery-2.2.3.js";
    var fileref = document.createElement('script');
    fileref.setAttribute("type","text/javascript");
    fileref.setAttribute("src", filename);

    if (typeof fileref!="undefined")
    {
      var scriptparent = document.getElementsByTagName("head")[0];

      if (typeof scriptparent=="undefined")
      {
        var scriptparent = document.createElement('head');
        document.getElementsByTagName("html")[0].appendChild(scriptparent);
      }
      scriptparent.appendChild(fileref);
    }

    if (r_count<r_max)
    {
      setTimeout(Init, 100);
      return 0;
    }
    else
    {
      console.log("Failed to load smoothscroll!");
    }
    r_count++;
  }
  if (OWNJQUERY) {
    var versiontable = $0.fn.jquery.split('.');
    var version = 0;
    for (var i = versiontable.length-1; i >= 0; i--) { 
      var power = versiontable.length-i;
      version += Math.pow(10,power-1)*versiontable[i];
    }

    console.log("Script jQuery OK! Version: " + version);
    InitSmoothscroll();	
  }
  if (OLDJQUERY) {
    console.log("Restoring old jQuery...");  
    $ = old$;
    jQuery = oldjQuery;
    var versiontable = $.fn.jquery.split('.');
    var version = 0;
    for (var i = versiontable.length-1; i >= 0; i--) { 
      var power = versiontable.length-i;
      version += Math.pow(10,power-1)*versiontable[i];
    }

    console.log("Page jQuery OK! Version: " + version);
  }
  console.log("Finished loading smoothscroll!");
}

console.log("Loading smoothscroll...");
Init();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址