Smoothscroll

Smooth scrolling on pages using javascript

ของเมื่อวันที่ 08-03-2018 ดู เวอร์ชันล่าสุด

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey to install this script.

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name Smoothscroll
// @author       Creec Winceptor
// @description  Smooth scrolling on pages using javascript
// @namespace https://greasyfork.org/users/3167
// @include     *
// @version 5.1
// ==/UserScript==

//dev
var DEBUG = false;
var REFRESHRATE = 60;

//settings
var SMOOTHNESS = 0.5;
var ACCELERATION = 0.5;


function IsScrollable(element, dir)
{
	var checkradius = 2; //pixels to try scrolling

	if (dir>0)
	{
		dir = checkradius;
	}
	if (dir<0)
	{
		dir = -checkradius;
	}

	var originalscroll = element.scrollTop;
	var testscroll = Math.round(originalscroll + dir);
	element.scrollTop = testscroll;

	var scrollable = Math.round(element.scrollTop)==testscroll;
	element.scrollTop = originalscroll;

	return scrollable;
}

function HasScrollbars(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";

	//body or html always have scrollbars
	var scrollbar3 = element==document.body || element==document.documentElement;

	return scrollbar1 || scrollbar2 || scrollbar3;
}

function Direction(number)
{
  if (number>0)
  {
    return 1;
  }
  if (number<0)
  {
    return -1;
  }
  return 0;
}

function Timeout(element, newtimeout)
{
  if (newtimeout!=undefined)
  {
    var oldtimeout = element.ScrollTimeout;
    if (oldtimeout!=undefined)
    {
      clearTimeout(oldtimeout);
    }
    element.ScrollTimeout = newtimeout;
    return newtimeout;
  }
	else
  {
    var oldtimeout = element.ScrollTimeout;
    if (oldtimeout!=undefined)
    {
      return oldtimeout;
    }
    return null;
  }
}

function ScrollSubpixels(element, newvalue)
{
  if (newvalue!=undefined)
  {
    element.scrollsubpixels = newvalue;
    return newvalue;
  }
	else
  {
    var olddelta = element.scrollsubpixels;
    if (olddelta!=undefined)
    {
      return olddelta;
    }
    return 0;
  }
}
function ScrollPixels(element, newvalue)
{
  if (newvalue!=undefined)
  {
    element.scrollpixels = newvalue;
    
    ScrollSubpixels(element, 0);
    
    return newvalue;
  }
	else
  {
    var olddelta = element.scrollpixels;
    if (olddelta!=undefined)
    {
      return olddelta;
    }
    return 0;
  }
}

function GetTarget(e) {
  var direction = e.deltaY;
  var nodes = e.path;
  
  for (var i=0; i<nodes.length; i++) { 
    var node = nodes[i];
    if (IsScrollable(node, direction) && HasScrollbars(node))
    {
      if (DEBUG) {
        console.log("scrollbar: ");
        console.log(node);
      }
      return node;
    }
  }

  return null;
}

function AnimateScroll(target) {
  var updaterate = Math.floor(1000/(REFRESHRATE));
  
  var scrollsubpixels = ScrollSubpixels(target);
  var scrollpixels = ScrollPixels(target);

  var scrolldirection = Direction(scrollpixels);

  var scrollratio = 1-Math.pow( REFRESHRATE, -1/(REFRESHRATE*SMOOTHNESS));
  
  var scrollrate = scrollpixels*scrollratio;
  
  if (Math.abs(scrollpixels)>1) {
    
    var fullscrolls = Math.floor(Math.abs(scrollrate))*scrolldirection;
    var scrollsubpixelsadded = scrollrate - fullscrolls;

    var additionalscrolls = Math.floor(Math.abs(scrollsubpixels + scrollsubpixelsadded))*scrolldirection;
    var scrollsubpixelsleft = scrollsubpixels + scrollsubpixelsadded - additionalscrolls;

    ScrollPixels(target, scrollpixels-fullscrolls-additionalscrolls);
    ScrollSubpixels(target, scrollsubpixelsleft);
	
	  target.scrollTop += fullscrolls + additionalscrolls;

    Timeout(target, setTimeout(function() {

      AnimateScroll(target);
    }, updaterate));
  } else
  {
    ScrollPixels(target, 0);
  }
  
}

function StopScroll(e) {
  var nodes = e.path;
  
  for (var i=0; i<nodes.length; i++) { 
    var node = nodes[i];
    ScrollPixels(node, null);
    Timeout(node, null);
  }
}

function StartScroll(e, target) {
  var direction = e.deltaY;
  
  var scrollpixels = ScrollPixels(target);

  var accelerationratio = Math.sqrt(Math.abs(scrollpixels/direction*ACCELERATION));
  
  var acceleration = Math.round(direction*accelerationratio);

  ScrollPixels(target, scrollpixels + direction + acceleration);
 
  if (e.defaultPrevented)
  {
    return true;
  }
  else
  {
    AnimateScroll(target);
    e.preventDefault();
  }
}


function WheelEvent(e) {
  var target = GetTarget(e);
  
  if (target) {
    StartScroll(e, target);
  }
}

function ClickEvent(e) {
  StopScroll(e);
}

function Init()
{
  if (window.SMOOTHSCROLL) {
    console.log("Smoothscroll: already loaded");
    return null;
  }
  
  if (window.top != window.self) {
    console.log("Smoothscroll: ignoring iframe");
    return null;
  }
  
  document.documentElement.addEventListener("wheel", function(e){
    WheelEvent(e);
    
    if (DEBUG) {
      console.log(e);
    }
  });

  document.documentElement.addEventListener("mousedown", function(e){
    ClickEvent(e);
    
    if (DEBUG) {
      console.log(e);
    }
  });
  
  console.log("Smoothscroll: loaded");
  window.SMOOTHSCROLL = true;
}
Init();